0

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

dennis
  • 442
  • 2
  • 17
  • I believe that by default typescript doesn't do extraneous key checking. It only verifies what needs to be in the object. – Russley Shaw Jul 19 '17 at 18:14
  • 1
    Why not? In {red: true, green: true} it perfectly identifies that red can be used, but green cannot. – dennis Jul 19 '17 at 18:41

1 Answers1

2

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
eusoj
  • 372
  • 3
  • 12
  • Yes, I understand that. But why is T an array? T should be of type "red" | "round" to the compiler. – dennis Jul 19 '17 at 18:34
  • 1
    `HasMods` *might* be an array, and that's just the way TypeScript [deals with](https://github.com/Microsoft/TypeScript/issues/14383) excess properties on union types. – jcalz Jul 19 '17 at 18:38