項目16 インデックスシグネチャよりも適切な代替手段を使う
JavaScriptのオブジェクト
JavaScriptのオブジェクトは文字列(またはSymbol)のキーを任意の型の値にマップしたもの
TypeScriptでは、型にインデックスシグネチャを指定することで実現可能
インデックスシグネチャ
code:ts
type Rocket = {property: string: string};
const rocket: Rocket = {name: 'Falcon 9', variant: 'v1.0',thrust: '4,940 kN'};
キーの名前
純粋にドキュメンテーションのためのもの。型チェッカーによる影響は受けない
キーの型
string,number,symbol, テンプレートリテラル型または、これらのユニオンでなければならない
ただし、numberの利用は避ける
値の型
どんな型でもOK
問題点
どんなキーでも受け入れてしまう
nameの代わりにNameと入力してもうけれてしまう
特定のキーの存在を要求しない
{}でも有効
キーごとに異なる型を持てない
TypeScriptの言語サービスを受けれない
オートコンプリートが効かない
インデックスシグネチャはあまり正確でないので、多用厳禁
インデックスシグネチャの代案
別途型定義をする
code:ts
interface Rocket {name: string;variant: string;thrust_kN: number;}
const falconHeavy: Rocket = {name: 'Falcon Heavy',variant: 'v1',thrust_kN: 15200};
動的なデータをモデリングする際はMap型を使う
code:ts
function parseCSVMap(input: string): Map<string, string>[] {
const lines = input.split('\n');
const headerLine, ...rows = lines;
const headers = headerLine.split(',');
return rows.map(rowStr => {
const row = new Map<string, string>();
rowStr.split(',').forEach((cell, i) => {
row.set(headersi, cell);
});
return row;
});
}
Recordを使用する
code:ts
type Vec3D = Record<'x' | 'y' | 'z', number>;
// ^? type Vec3D = {
// x: number;
// y: number;
// z: number;
// }
限られたフィールドしか持たないのであれば、インデックスシグネチャの利用は避ける
余剰プロパティチェックを無効にする
インデックスシグネチャを使えば、余剰プロパティチェックを無効化できる
特定のプロパティ以外に、追加したい場合に有効
code:ts
interface ButtonProps {
title: string;
onClick: () => void;
otherProps: string: unknown;
}
renderAButton({
title: 'Roll the dice',
onClick: () => alert(1 + Math.floor(20 * Math.random())),
theme: 'Solarized', // OK
});
#TypeScript