2016-10-06 4 views
1

signature of Object.assignを見ると、交差の種類が使用されていることがわかりますが、その動作は予期したものではありません。TypeScript Object.assign confusion

私はObject.assignを使っていくつかの変更を古いオブジェクトとマージして新しいオブジェクトを作成します(不変のデータパターンに従うときJSの一般的な習慣と同じです)。そして、TypeScriptが部分と結果が正しいことを検証しますTypeScriptは何もせずにエラーなしで可能です。例えば

interface Thing { 
    name: string; 
    age: number; 
    fav: boolean; 
} 

let oldThing: Thing = { 
    name: "Aaa", 
    age: 123, 
    fav: false 
}; 

let newThing: Thing = Object.assign({}, oldThing, { 
    name: "Bbb", 
    age: "abc", // should be type error 
    fake: "fakey" // should be unknown prop error 
}); 

Here it is in the playground.

なぜObject.assignは、この間違った割り当てはThingできるようにするのでしょうか?この仕事を私が期待していたものに近づける方法はありますか?

+0

あなたはそれがjavascrだtypescriptですコンパイラを幸せにするためにすべての要件を満たしますが、一日の終わりに覚えてきましたあなたのコードとjavascriptを実行するiptは気にしません。 –

+0

ねえ、私はいつもそのことを思い出しています。 :)しかし、ここで私の質問は*コンパイル*ですか? 'Thing'への割り当ては、それらのプロパティのコンパイルエラーになるはずです。たぶん私は型チェッカーがどのように割り当てを検証するのか分かりません。 – Aaron

答えて

4

戻り値がのために構築された交差タイプが不合理で、実際の値で占有することができないという理由で、直感的にエラーが予想される理由があります。しかし、TypeScriptにはこれを確認する方法がありません。ここObject.assignからの戻り値は以下のように入力されている:もちろん

{ 
    name: string, 
    age: string & number, 
    fav: boolean, 
    fake: string 
} 

が両方string & numberある実際の値はありませんが、コンパイラはそれを知りません。それはうまくいけば、この不条理な型を構築し、Thingにそれを代入しようとすると、Thingの各プロパティの型が戻り値の対応するプロパティによって満たされていることを検証します。この場合(それぞれname,ageおよびfavが存在し、少なくともThingの必須インターフェイスを満たしているため)、割り当てが成功します。

あなたがnewThingの種類を推測することを許可した場合、その後、ageプロパティに何も割り当ててみました、あなたは問題を参照してくださいね。

let newThing = Object.assign({}, oldThing, { 
    name: "Bbb", 
    age: "abc", 
    fake: "fakey" 
}); 
newThing.age = 10; // Compiler error because 10 is not a string 
newThing.age = "10"; // Compiler error because "10" is not a number 
+1

おかげさまで、*ファンキーです。ですから、 'Object.assign'は、このような型の安全性を実践するのに本当に役立たないと思います。代わりにTSをサポートするオブジェクトが普及するのを楽しみにしています... – Aaron

0

あなたがで<シング>を追加することによって、チェックするために活字を強制することができますフロント:

interface Thing { 
    name: string; 
    age: number; 
    fav?: boolean; // You may need to mark this as optional depending on 
        // your requirement, otherwise TypeScript will 
        // generate missing prop error 
} 

//... 

let newThing: Thing = Object.assign({}, oldThing, <Thing>{ 
    name: "Bbb", 
    age: "abc",  // will generate type error 
    fake: "fakey" // howerver, this will not generate unknown prop error 
});