TypeScript 中奇怪的联合类型行为
Strange union type behavior in TypeScript
谁能解释 TypeScript (2.4.1) 中的以下行为?
场景:我有一个按钮,可以是 "red" 或 "red and round"(修改)。我想用以下语法来描述它:
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 ???
为什么值 "map" 对我的类型为 { [key in T]?: boolean } 的对象有效,其中 T 是 "red" | "round"? "map" 既不是 "red" 也不是 "round"。
实际上,所有数组方法在这里都有效 - "every"、"copyWithin" 等...
如果您查看数组的 proto 定义,"map" 是属性之一。
所以当你比较时 "map in T" 它是真的,因为它是在一个数组结构中比较的,如果它是一个对象它将是假的
console.log("map" in {"element":4}) // false
console.log("map" in [4]) //true
谁能解释 TypeScript (2.4.1) 中的以下行为?
场景:我有一个按钮,可以是 "red" 或 "red and round"(修改)。我想用以下语法来描述它:
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 ???
为什么值 "map" 对我的类型为 { [key in T]?: boolean } 的对象有效,其中 T 是 "red" | "round"? "map" 既不是 "red" 也不是 "round"。
实际上,所有数组方法在这里都有效 - "every"、"copyWithin" 等...
如果您查看数组的 proto 定义,"map" 是属性之一。
所以当你比较时 "map in T" 它是真的,因为它是在一个数组结构中比较的,如果它是一个对象它将是假的
console.log("map" in {"element":4}) // false
console.log("map" in [4]) //true