TypeScript: Handbook – Utility Types#Record<Keys,Type\>
Record は次の様にある型とある型の組み合わせが全てあることを保証する組み込みの型です。
// @see https://www.typescriptlang.org/docs/handbook/utility-types.html#recordkt
interface PageInfo {
title: string;
}
type Page = 'home' | 'about' | 'contact';
// 第一引数の型をkey、 第二引数の型をvalueに取るオブジェクトの型を定義します。連想配列っぽい感じです
const x: Record<Page, PageInfo> = {
about: { title: 'about' },
contact: { title: 'contact' },
home: { title: 'home' },
};
const y: Record<number, PageInfo> = {
// about: { title: 'about' }, // stringをキーに持つとNG
3 : { title: 'three' } // numberをキーに持つならばOK
};
key となる型の要素が増えた場合、対応する部分を全て埋める必要があるのがよいところです。ある要素を追加した後に、そのある要素に対応する○○な部分の追加を作るのを忘れていた、といった潜在的バグを防げます(こういった時は JavaScript 言語としてのエラーにならず謎の undefined が登場するのみのユーザ的、開発者的エラーにしかならない場合が多いです)。
具体的には次です。
// 何か適当な状態定数とその状態の意味を表す名前の型の定義。enumが好きな人はenumを使った方がやりやすいです
type STATUS_A = 0;
type STATUS_SUCCESS = 1;
type STATUS_ERROR = 2;
type STATUS_UNKNOWN = 3;
// ↑のステータスを表す型をグループ化
type STATUS = STATUS_A | STATUS_SUCCESS | STATUS_ERROR | STATUS_UNKNOWN;
// グループ中の各ステータスに対応する option 要素のプロパティの設定
// Partial<HTMLOptionElement> は option 要素のプロパティの設定の全てが undefined かもしれないしあるかもしれない、の意。予測補完に便利
const statusOptions: Record<STATUS, { label: string } & Partial<HTMLOptionElement>> = {
0: { label: 'A', value: '0', dataset: { msg: 'this is STATUS_A' } },
1: { label: '正常終了', value: '1' },
2: { label: 'エラー', value: '2' },
3: { label: '謎', value: '3' },
};
// グループ中の各ステータスに対応する背景色の設定
const statusBackground: Record<STATUS, { backgroundColor: BackgroundColorProperty }> = {
0: { backgroundColor: 'aliceblue' },
1: { backgroundColor: '#16ff03' },
2: { backgroundColor: 'red' },
3: { backgroundColor: 'rgba(0,0,0,0)' },
};
こんな感じである要素を表現する型とその要素に対応する何かしらを Record 型で表現します。こうすると次の様に要素を増やしたときに TypeScript が型を満たせていない、とコンパイルエラーを出力してくれます。このコンパイルエラーがあるうちは追加分の対応が完了していない、ということになり追加忘れを防いでくれます。例は近場のファイルで変更箇所も二か所と恩恵が薄いですが大規模になるほど効果が現れます。
// 何か適当な状態定数とその状態の意味を表す名前の型の定義。enumが好きな人はenumを使った方がやりやすいです type STATUS_A = 0; type STATUS_SUCCESS = 1; type STATUS_ERROR = 2; type STATUS_UNKNOWN = 3; type STATUS_ADDITIONAL = 9; // この行を追加 // ↑のステータスを表す型をグループ化 type STATUS = STATUS_A | STATUS_SUCCESS | STATUS_ERROR | STATUS_UNKNOWN | STATUS_ADDITIONAL; // 末尾に追加 // 以下は前述のコードと同じなので省略
