23

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

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

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

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

编译器开始抱怨。

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

4

1 回答 1

29

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

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

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

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

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

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


实际上,这里的规则是允许你丢弃返回值,这与例如 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'
于 2012-10-06T21:06:26.243 回答