TypeScriptの lookup型 と keyof型 について、混乱することがあったので基本的な使い方をまとめました。
lookup型
T[K] という構文を持つ型で、lookup型を使うと、オブジェクトや配列などの型から特定のプロパティやインデックスの型を取り出すことができます。
オブジェクト型から特定のプロパティを指定して、そのプロパティの型を取得します。
type Animals = {
dog: {
breed: string;
isTrained: boolean;
};
cat: {
color: string;
age: number;
};
};
type DogDetails = Animals["dog"];
// { breed: string; isTrained: boolean; }
type CatAge = Animals["cat"]["age"]
// number
上記の例では、Animals
型のdog
プロパティの型と、cat
プロパティの中のage
の型を取得しています。
このように、既存の型を再利用するのがlookup型の基本的な使い方となります。
特定のインデックスを指定して、それに対応する型を取得します。
const animals = ['dog', 'cat', 'horse', 'rabbit', 'bird'] as const
// animalsの型は、readonly ['dog', 'cat', 'horse', 'rabbit', 'bird']
type Rabbit = (typeof animals)[3]
// "rabbit"
type Animal = (typeof animals)[number]
// "dog" | "cat" | "horse" | "rabbit" | "bird"
上記の例では、変数animals
の型を typeof で取得し、その取得した型に対してインデックスを指定することでそれに対応したrabbit
型を得ています。
また、[number] を指定することにより、すべてのインデックス(要素)に対応する型をユニオン型で取得することができます。
keyof型
keyof T という構文で、オブジェクト型からそのオブジェクトのプロパティ名の型を取得することができます。一般に、keyof型の結果は文字列のリテラル型となります。
type Dog = {
age: number;
sex: 'male' | 'female' | 'unknown';
breed: string;
isTrained: boolean;
};
type DogKeys = keyof Dog;
// "age" | "sex" | "breed" | "isTrained"
const dog = {
age: 3,
sex: 'female',
breed: 'chihuahua',
isTrained: true
};
type DogKeys = keyof typeof Dog;
// "age" | "sex" | "breed" | "isTrained"
この例では、変数dog
からオブジェクト型のプロパティ名を文字列のリテラル型として取得しています。
keyof型 と lookup型 を組み合わせて、オブジェクトのプロパティ値の型をユニオン型として取得することができます。
const dog = {
age: 3,
sex: 'female',
breed: 'chihuahua',
isTrained: true
};
const cat = {
age: 5,
sex: 'male',
breed: 'american shorthair',
color: 'white'
} as const;
type ValueOf<T> = T[keyof T]
type DogValues = ValueOf<typeof dog>
// string | number | boolean
type CatValues = ValueOf<typeof cat>
// 5 | "male" | "american shorthair" | "white"
ここで注目すべきポイントは keyof T です。ここではTがどのような型になるのか決まっていませんが keyof を使うことができます。つまり、keyof は型引数に対しても有効に作用します。
以上が、lookup型 と keyof型 の基本的な使い方となります。これらを使いこなすことで、型安全を維持しながら柔軟で再利用性の高い型定義が可能になります。また今回は触れませんでしたが、ジェネリクスを用いると、型の制約を動的に設定したり、汎用的な型を作成することが可能になり、より高度な型操作を実現できます。