インデックス型 (index signature)
TypeScriptで、オブジェクトのフィールド名をあえて指定せず、プロパティのみを指定したい場合があります。そのときに使えるのがこのインデックス型(index signature)です。たとえば、プロパティがすべてnumber
型であるオブジェクトは次のように型注釈します。
typescript
let obj: {[K: string]: number;};
typescript
let obj: {[K: string]: number;};
フィールド名の表現部分が[K: string]
です。このK
の部分は型変数です。任意の型変数名にできます。K
やkey
にするのが一般的です。string
の部分はフィールド名の型を表します。インデックス型のフィールド名の型はstring
、number
、symbol
のみが指定できます。
インデックス型のオブジェクトであれば、フィールド名が定義されていないプロパティも代入できます。たとえば、インデックス型{ [K: string]: number }
には、値がnumber型であれば、a
やb
など定義されていないフィールドに代入できます。
typescript
let obj: {[K: string]: number;};obj = { a: 1, b: 2 }; // OKobj.c = 4; // OKobj["d"] = 5; // OK
typescript
let obj: {[K: string]: number;};obj = { a: 1, b: 2 }; // OKobj.c = 4; // OKobj["d"] = 5; // OK
コンパイラーオプションのnoUncheckedIndexedAccess
を有効にした場合、インデックス型では、プロパティの型は自動的にプロパティに指定した型とundefined型のユニオン型になります。これは、プロパティが存在しないときに、値がundefined
になるのを正確に型で表すためです。
typescript
const obj: { [K: string]: number } = { a: 1 };const b: number | undefined = obj.b;console.log(b); //=> undefined
typescript
const obj: { [K: string]: number } = { a: 1 };const b: number | undefined = obj.b;console.log(b); //=> undefined
#
Record<K, T>を用いたインデックス型インデックス型はRecord<K, T>
ユーティリティ型を用いても表現できます。次の2つの型注釈は同じ意味になります。
typescript
let obj1: { [K: string]: number };let obj2: Record<string, number>;
typescript
let obj1: { [K: string]: number };let obj2: Record<string, number>;