【问题标题】:TypeScript: void return type converted to any type?TypeScript:void 返回类型转换为任何类型?
【发布时间】:2012-10-06 16:34:04
【问题描述】:

我似乎无法理解为什么以下代码不会引发错误:

var rg: {(): void;}[] = [];
rg.push(function():string {return "";})

我明确声明该类型应该是返回void 的函数数组,但是我推送了一个返回string 的函数,但编译器并没有抱怨。如果我将rg 的定义更改为

var rg: {():number;}[] = [];

编译器开始抱怨。

这是一个错误还是 void 返回类型应该如何工作(即,如果使用 void,则一切正常,基本上与返回类型 any 相同)?

【问题讨论】:

    标签: typescript


    【解决方案1】:

    这是设计使然(我将很快解释为什么它是好的设计)。规范说(在第 3.6.3 节中,为清楚起见进行了删节):

    如果满足以下条件之一,则类型 S 可分配给类型 T,并且 T 可从 S 分配...

    • S 和 T 是对象类型,对于 T 中的每个成员 M,以下其中一项为真:

      • M 是调用、构造或索引签名,S 包含调用、构造或索引签名 N,其中

        • M 的结果类型是 Void,或者 N 的结果类型可以分配给 M 的结果类型。

    在这种情况下,我们正在测试 () => string 是否可以分配给 () => void。所以string 必须可以分配给void(不是),或者void 必须是void(可以)。


    实际上,这里的规则是您可以丢弃返回值,这与例如C++ 在模板解析中处理void

    function decrementWidgetHeight(w: Widget): number {
        // ... returns the new height of the widget
    }
    
    function applyToManyWidgets(w: Widget[], change: (x: Widget) => void): void {
        // for each widget in the array, apply 'change' to it
    }
    
    // Later...
    applyToManyWidgets(widgetsToShorten, decrementWidgetHeight); // Should be allowed?
    

    当我们将change 的类型限制为(widget) => void 时,我们这样做是为了让您可以将decrementWidgetHeight 作为第二个参数传递,即使它有返回值,但是 仍然确保当我们编写applyToManyWidgets 的主体时,我们不会在任何地方意外使用change 的返回值。

    请注意,void 仍然不同于 any,因为这是不允许的:

    function f() { }
    var x = f(); // Disallowed, f() is of type 'void'
    

    【讨论】:

    • +1 - 您可以在 TypeScript 游乐场中使用:var rg: {(): void;}[] = []; rg.push(function():string {return "";}) var x = rg[0](); 进行测试,以查看实际行为。将void 更改为string,它将允许使用返回值。
    • 好吧,这是有道理的,但有点反直觉,即允许添加与类型不匹配的函数,即使它在定义中是无效的。
    • 规范还说“void 只与未定义、空和任何类型有关”,所以我不确定规范是否一致。绝对出乎意料。
    • 从 1.4.1.0 版开始,我可以看到允许分配 void 函数调用
    • 感谢您的回答瑞恩!不过我确实有一个follow-up question,因为这种行为在处理承诺时会造成麻烦。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-05-31
    • 1970-01-01
    • 2020-11-24
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多