TypeScriptでオブジェクトの動的キー割り当てエラーを回避する方法


8

次のようなTypeScriptコードがあるとします。

type User = {
  id: number,
  name: string,
}

let user1: User = {id: 123, name: "Hello"};
let user2: User = {id: 456, name: "World"};

let keys: (keyof User)[] = ["id", "name"];

for (let key of keys) {
  user1[key] = user2[key];
}

これはエラーになります

Type 'string | number' is not assignable to type 'never'.

ステートメントについて

user1[key] = user2[key];

の定義をkeystoに変更すると

let keys: string[] = ["id", "name"];

エラーはなくなりますが、タイプセーフは失われます。

タイプセーフを維持しながらこのエラーを回避できる方法はありますか?


1
let keys: string[]はエラーを削除しますが、TSはそのことを保証できないuser1[key]user2[key]有効であるため、別のエラーを導入します。
VLAZ、

@VLAZはい、let keys: string[]別の問題が発生しますが、それは実行時エラーになります(配列に存在しないフィールド名が値として含まれている場合)。私たちが探しているのは、それを回避するためのコンパイル時チェックです。
Vaibhav K

回答:


5

ここで型のアサーションを回避する良い方法はありません。TSの最近のバージョン(3.5以降)では、インデックスを介して書き込むときに、書き込まれる値は、キーで指定されたすべての可能なプロパティ値と互換性がある必要があります。あなたの場合、それはそれゆえにエラーにnumber & string減少するでしょうnever

根本的な原因は、TSがタイプの変数のみを追跡しないことです。そのため、タイプに関する限り、例は以下と同じです。

let key1 = 'id' as  keyof User;
let key2 = 'name' as  keyof User;
//Obvious error
user1[key1] = user2[key2] // same error, TS can't distingusih between this and your user1[key] = user2[key]

最も簡単な解決策は、あなたのケースでこれが問題ないと確信している場合、型アサーションを使用することです:

type User = {
  id: number,
  name: string,
}


let user1: User = { id: 123, name: "Hello" };
let user2: User = { id: 456, name: "World" };
for (let key of keys) {
  user1[key] = user2[key] as never
}

演奏する

代わりに(ただし、これ以上のタイプセーフではありません)T[K]、インデックス値に割り当て可能な小さな抜け穴を使用できます。

type User = {
  id: number,
  name: string,
}


let user1: User = { id: 123, name: "Hello" };
let user2: User = { id: 456, name: "World" };

let keys: (keyof User)[] = ["id", "name"];

for (let key of keys) {
  set(user1, key, user2[key])
}

演奏する


ご回答ありがとうございます。理想的ではありませんが、as never機能します。また、set2番目の例の方法を説明できますか?
Vaibhav K
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.