TypeScript のルックアップ型を使うと、定義済みの型の一部分を取り出すことができる。
keyof
キーワードと組み合わせることで、オブジェクトの各キーの型を取り出すこともできる。
この記事の内容は TypeScript のv3.9.5
で動作確認している。
ルックアップ型の使い方
定義済みの型["キー"]
と書くことで、指定したキーに対応する型を取り出すことができる。
これをルックアップ型という。
type Foo = { a: number; b: string; c?: boolean; }; type X = Foo["a"]; // type X = number type Y = Foo["b"]; // type Y = string type Z = Foo["c"]; // type Z = boolean | undefined
存在しないキーにアクセスしようとすると、エラーになる。
type Q = Foo["d"]; // Property 'd' does not exist on type 'Foo'.ts(2339)
入れ子になっていても、問題なく使える。
type APIResponse = { user: { id: number; name: string; note?: string; }; }; type A = APIResponse["user"]["id"]; // type A = number type B = APIResponse["user"]["name"]; // type B = string type C = APIResponse["user"]["note"]; // type C = string | undefined
配列の要素は [number] で取り出せる
配列の場合、キーとして[number]
を指定することで、要素を取り出せる。
type Foo = string[]; type A = Foo[number]; // type A = string type Bar = (string | boolean)[]; type B = Bar[number]; // type B = string | boolean
タプルの場合は、number
ではなくそのリテラル型を使うことで、インデックスを指定して要素を取り出せる。
type Foo = [boolean, string]; type A = Foo[number]; // type A = string | boolean type B = Foo[0]; // type B = boolean type C = Foo[1]; // type C = string
存在しないキーを指定するとエラーになる。
type D = Foo[2]; // Tuple type 'Foo' of length '2' has no element at index '2'.ts(2493)
ルックアップ型と keyof キーワードを組み合わせる
keyof
キーワードは、オブジェクトのキーをstring
の共用体型として取り出す機能。
type Foo = { a: number; b: string; }; type A = keyof Foo; // type A = "a" | "b"
keyof
はオブジェクトの各キーの名前を取り出す機能だが、これをルックアップ型と組み合わせることで、オブジェクトの各キーの(名前ではなく)型を取り出すことができる。
type Foo = { a: number; b: string; }; type A = keyof Foo; // type A = "a" | "b" type B = Foo[keyof Foo]; // type B = string | number
以下のextractFromAPIResponse
はオブジェクトから一部の値を取り出す関数だが、このような関数の型も、ルックアップ型とkeyof
キーワードで表現できる。
type User = { id: number; name: string; note?: string; }; type APIResponse = { user: User; isPremiumUser: boolean; }; const extractFromAPIResponse = ( apiResponse: APIResponse, key: keyof APIResponse, ): APIResponse[keyof APIResponse] => { return apiResponse[key]; }; const sampleData: APIResponse = { user: { id: 1, name: "Alice", }, isPremiumUser: true, }; extractFromAPIResponse(sampleData, "user"); // boolean | User extractFromAPIResponse(sampleData, "wrongKey"); // Argument of type '"wrongKey"' is not assignable to parameter of type '"user" | "isPremiumUser"'.ts(2345)
keyofStringsOnly フラグについて
keyof T
は、string | number | symbol
のサブタイプである。
type Foo = keyof any; // type Foo = string | number | symbol
そのため、キーとしてnumber
やsymbol
を使っていたとしても、それをそのまま取得できる。
const sym = Symbol(); type Bar = { a: unknown; 1: unknown; [sym]: unknown; }; type A = keyof Bar; // type A = typeof sym | "a" | 1
文字列以外のキーを無視したい場合は、tsconfig.json
のkeyofStringsOnly
を有効にする。
{ "compilerOptions": { "keyofStringsOnly": true } }
type Foo = keyof any; // type Foo = string const sym = Symbol(); type Bar = { a: unknown; 1: unknown; [sym]: unknown; }; type A = keyof Bar; // type A = "a"