2012-10-06 116 views
17

我似乎無法理解爲什麼下面的代碼不會引發錯誤:TypeScript:void返回類型轉換爲任何類型?

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

我明確指出,該類型應爲返回void功能的陣列,但是我把那裏返回函數一個string,但編譯器不抱怨。如果我將rg的定義更改爲

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

編譯器開始抱怨。

這是一個錯誤還是無效返回類型應該如何工作(即如果使用void,基本上使其與返回類型any相同,什麼都會發生?

+0

我日提交的問題(http://typescript.codeplex.com/workitem/139)。 –

回答

17

這是由設計(我會解釋爲什麼它很好的設計很快)。細則中指出(在第3.6.3,刪節爲清楚起見):

A type S is assignable to a type T, and T is assignable from S, if one of the following is true...

  • S and T are object types and, for each member M in T, one of the following is true:

    • M is a call, construct or index signature and S contains a call, construct or index signature N where

      • the result type of M is Void, or the result type of N is assignable to that of 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' 
+0

+1 - 你可以用下面的方法測試它:var rg:{():void;} [] = []; rg.push(函數():字符串{返回「」;})var x = rg [0]();'在TypeScript操場中查看行爲的行爲。將'void'改爲'string',它將允許使用返回值。 – Fenton

+0

好吧,它是有道理的,但有點直觀,即允許添加一個不匹配類型的函數,即使它在定義中是無效的。 –

+1

該規範還規定「void僅與Undefined,Null和Any類型有關」,所以我不確定規範是否一致。絕對意外。 – Roly

0

看起來像一個錯誤。你應該打開一個new work item的問題

+0

[Did that](https://typescript.codeplex.com/workitem/1734),但考慮到上面的評論,我想這是打算。在目前爲止,在TS中沒有找到多少用到的泛型... – Roly