TypeScript中奇怪的联合类型行为

时间:2017-07-19 18:05:09

标签: javascript typescript discriminated-union

有人能解释TypeScript(2.4.1)中的以下行为吗?

场景:我有一个按钮,可能是"红色"或者"红色和圆形" (变形例)。我想用以下语法来描述它:

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 ???

为什么值&#34; map&#34;对于我的{{key in T]对象有效?:boolean}其中T是&#34; red&#34; | &#34;轮&#34 ;? &#34;映射&#34;既不是&#34;红色&#34;或者&#34; round&#34;。

实际上,所有数组方法在这里都有效 - &#34;每个&#34;,&#34; copyWithin&#34;等...

1 个答案:

答案 0 :(得分:2)

如果您查看数组的 proto 定义,“map”就是其中一个属性。

所以,当你比较“T中的map”时,这是真的,因为它是在数组结构中进行比较的,如果它是一个对象则会是假的

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