2017-07-19 33 views
0

任何人都可以在TypeScript(2.4.1)中解釋以下行爲嗎?TypeScript中的奇怪聯合類型行爲

場景:我有一個可能是「紅色」或「紅色和圓形」(修改)的按鈕。我想有以下語法來形容它:

button.mods = "red"; 
button.mods = ["red", "round"]; 
button.mods = { red: true, round: false }; 

來形容這一切,我用了以下接口:

interface HasMods<T extends string>{ 
    mods: T | T[] | { [key in T]?: boolean } 
} 

interface Button extends HasMods<"round" | "red"> { 
} 

好了,現在我們可以做一些測試:

let b: Button; 
b.mods = "red"; //ok, correct 
b.mods = "green"; //error, correct 

b.mods = ["red"]; //ok, correct 
b.mods = ["green"]; //error, correct 

b.mods = {red: true}; //ok, correct 
b.mods = {red: true, green: true}; //error, correct 

到目前爲止,一切都很完美。 但現在是個謎:

b.mods = {red: true, map: false}; //ok, why ??? 

爲什麼值「地圖」有效期爲我喜歡的類型的對象{[在T鍵] ?:布爾},其中T是「紅」 | 「回合」? 「地圖」既不是「紅色」,也不是「圓形」。

實際上,所有的陣列方法是有效的在這裏 - 「每一個」,「copyWithin」,等等

+0

我相信默認情況下,typescript不會執行多餘的密鑰檢查。它只驗證對象中需要什麼。 –

+1

爲什麼不呢?在{red:true,green:true}中,它完美地表示可以使用紅色,但綠色不能。 – dennis

回答

2

如果走在陣列的定義一看,「地圖」是一屬性。

因此,當你比較「映射T」這是真的,因爲它是被一個數組結構內進行比較,如果它是一個對象會是假的

console.log("map" in {"element":4}) // false 
 
console.log("map" in [4]) //true

+0

是的,我明白這一點。但爲什麼是一個數組? T應該是類型「紅色」|向編譯器「四捨五入」。 – dennis

+1

'HasMods <「round」| 「red」> * *可能是一個數組,這就是TypeScript [處理](https://github.com/Microsoft/TypeScript/issues/14383)聯合類型過多屬性的方式。 – jcalz