インデックスシグネチャは、キーが事前に不明(または動的に追加される可能性がある)で、値が特定の型に一致するオブジェクトの型を記述するメカニズムです。コンパイル時にプロパティのリストが不明な辞書オブジェクト(map/dictionary)を作成することを可能にします。
問題の背景:JavaScriptでは、オブジェクトはしばしば連想配列として機能します。TypeScriptの静的型付けは、キーと値の型を指定することを要求します。インデックスシグネチャは、キーが固定されたプロパティではなく文字列(または数値)であり、値が特定の型であるオブジェクトを記述する主要な課題を解決します。
問題点:このようなオブジェクトを扱う際には、オブジェクトの既知のプロパティがインデックスシグネチャと競合したり、特定のプロパティに関する情報が失われることがあります。継承された型や辞書構造の拡張に関するニュアンスがあります。
解決策:インデックスシグネチャは、通常文字列または数値型のキーを使用して動的プロパティを記述するために使用されます。例えば、コレクション、キャッシュオブジェクト、またはAPIレスポンスの形式は{ [key: string]: T }です。型の制御を維持するためには、固定プロパティとインデックスシグネチャの両方を記述するか、必要に応じてユニオン型を構成する必要があります。
コード例:
interface StringNumberMap { [key: string]: number; } const map: StringNumberMap = { apples: 2, oranges: 5, bananas: 3 };
重要な特徴:
インデックスシグネチャのあるインターフェイスに不適合な型の固定プロパティを追加した場合、どうなりますか?
TypeScriptは、プロパティの型がインデックスシグネチャで指定された型と互換性がない場合、エラーを表示します。
interface BadDict { [key: string]: number; error: string; // エラー:stringはnumberと互換性がありません }
異なるキータイプ(数値と文字列)のインデックスシグネチャを同時に宣言できますか?
はい、可能ですが、1つ注意点があります:TypeScriptでは数値型のキーが自動的に文字列に変換されます。数値のインデックスシグネチャは、文字列キーの単なる同義語です。
interface NumStrDict { [key: string]: number; [key: number]: number; }
インデックスシグネチャの値にユニオン型やインターフェイスを使用できますか?
はい、値はユニオン型やインターフェイスになる可能性があります。このようにして、複雑なオブジェクトの辞書を記述することができます。
interface Dict { [key: string]: string | number; }
APIレスポンスのインターフェイスで[key: string]: anyを使用しました。後に返されるオブジェクトは異なる構造のデータを含み、ランタイムエラーを引き起こし、コードの保守が困難になりました。
利点:
欠点:
キャッシュオブジェクトのインターフェイスを記述し、値は明確に定義された型(例:UserData)であり、キーがuserId(string)であることをコメントで示しました。
interface UserCache { [userId: string]: UserData; }
利点:
欠点: