インデックス型 (index signature)
TypeScriptで、オブジェクトのフィールド名をあえて指定せず、プロパティのみを指定したい場合があります。そのときに使えるのがこのインデックス型(index signature)です。たとえば、プロパティがすべてnumber
型であるオブジェクトは次のように型注釈します。
ts
letobj : {[K : string]: number;};
ts
letobj : {[K : string]: number;};
フィールド名の表現部分が[K: string]
です。このK
の部分は型変数です。任意の型変数名にできます。K
やkey
にするのが一般的です。string
の部分はフィールド名の型を表します。インデックス型のフィールド名の型はstring
、number
、symbol
のみが指定できます。
インデックス型のオブジェクトであれば、フィールド名が定義されていないプロパティも代入できます。たとえば、インデックス型{ [K: string]: number }
には、値がnumber型であれば、a
やb
など定義されていないフィールドに代入できます。
ts
letobj : {[K : string]: number;};obj = {a : 1,b : 2 }; // OKobj .c = 4; // OKobj ["d"] = 5; // OK
ts
letobj : {[K : string]: number;};obj = {a : 1,b : 2 }; // OKobj .c = 4; // OKobj ["d"] = 5; // OK
コンパイラーオプションのnoUncheckedIndexedAccess
を有効にした場合、インデックス型では、プロパティの型は自動的にプロパティに指定した型とundefined型のユニオン型になります。これは、プロパティが存在しないときに、値がundefined
になるのを正確に型で表すためです。
ts
constobj : { [K : string]: number } = {a : 1 };constb : number | undefined =obj .b ;console .log (b );
ts
constobj : { [K : string]: number } = {a : 1 };constb : number | undefined =obj .b ;console .log (b );
📄️ noUncheckedIndexedAccess
インデックス型のプロパティや配列要素を参照したときundefinedのチェックを必須にする
Record<K, T>を用いたインデックス型
インデックス型はRecord<K, T>
ユーティリティ型を用いても表現できます。次の2つの型注釈は同じ意味になります。
ts
letobj1 : { [K : string]: number };letobj2 :Record <string, number>;
ts
letobj1 : { [K : string]: number };letobj2 :Record <string, number>;
📄️ Record<Keys, Type>
キー・バリューからオブジェクト型を作る
関連情報
📄️ Mapped Types
インデックス型では設定時はどのようなキーも自由に設定できてしまい、アクセス時は毎回undefinedかどうかの型チェックが必要です。入力の形式が決まっているのであればMapped Typesの使用を検討できます。