2017-07-19 4 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"> { 
} 

[OK]を、今、私たちはいくつかのテストを行うことができます。

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は「赤」での私のオブジェクトに対して有効なの「マップ」されます| "円形"? "map"は "red"でも "round"でもありません。実際

は、すべての配列方法は、ここで有効です - など「あらゆる」、「copyWithin」、...

+0

falseになります私は信じていますデフォルトでは、タイトスクリプトは無関係なキーチェックをしません。それは、オブジェクトに必要なものだけを検証します。 –

+1

どうしてですか? {red:true、green:true}では、赤は使用可能だが、緑は使用できないことを完全に識別します。 – dennis

答えて

2

あなたは、配列のプロト定義の中で見てみる場合は、「マップ」の一つであります属性。

それがオブジェクトであれば、あなたは「Tにマップ」を比較しているとき、それは配列構造の内部で比較されていますので、それは、本当だ、それは

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

+0

はい、わかりました。しかし、なぜTは配列ですか? Tは "red"タイプでなければなりません。コンパイラに「丸め」ます。 – dennis

+1

'HasMods <" round "| "red"> '*は配列であるかもしれませんが、これはユニオン型の型プロパティの超過プロパティです(https://github.com/Microsoft/TypeScript/issues/14383)。 – jcalz

関連する問題