Reputation: 610
Could anyone explain the following behavior in TypeScript (2.4.1)?
Scenario: I have a button which could be "red" or "red and round" (modifications). I would like to have the following syntax to describe it:
button.mods = "red";
button.mods = ["red", "round"];
button.mods = { red: true, round: false };
To describe all of this, I use the following interfaces:
interface HasMods<T extends string>{
mods: T | T[] | { [key in T]?: boolean }
}
interface Button extends HasMods<"round" | "red"> {
}
Ok, now we can do some testing:
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
So far everything is perfect. But now a mystery:
b.mods = {red: true, map: false}; //ok, why ???
Why is the value "map" valid for my object of type { [key in T]?: boolean } where T is "red" | "round"? "map" is neither "red" or "round".
Actually, all array methods are valid here - "every", "copyWithin", etc...
Upvotes: 0
Views: 92
Reputation: 374
If you take a look in the proto definition of the array, "map" is one of the attributes.
So when you're comparing "map in T" it's true, because it's being compared inside an array structure, if it were an object it will be false
console.log("map" in {"element":4}) // false
console.log("map" in [4]) //true
Upvotes: 2