動的オブジェクトはindex signatureで
index signature:「インデックスシグネチャー」と読む。
TypeScriptにおいてオブジェクトのプロパティ名やキーがあらかじめ決まっていない場合に、その型を定義するために使用される。
たとえば、JavaScriptオブジェクトではプロパティ名が動的に決まることがあるが、TypeScriptでは型安全性を保持するためにindex signatureを使う。
個人情報を扱うユーザークラスを作成する際、必要なプロパティがまだ決まっていないことがある。この場合、プロパティが増えるたびに都度定義を追加するのは手間がかかる。インデックスシグネチャーを使うことで、柔軟にプロパティを扱うことが可能。また、後でユニークなキーが必要になる場合など、プロジェクト途中での拡張にも役立つ。
基本構文
{ [key: string]: 型; }
key: string は任意の文字列のプロパティ名を表す。
型 はプロパティの値の型を指定する。
使用例
1. 文字列キーを持つオブジェクト
例えば、文字列のキーを持ち、値がnumber型であるオブジェクトを定義する場合:
interface NumberDictionary {
[key: string]: number;
}
const scores: NumberDictionary = {
"Alice": 90, "Bob": 85, "Charlie": 78, };
この場合、オブジェクトscoresは任意の文字列キーを持つことができ、値はnumber型であることが保証される。
2. 異なる型の値
index signatureを使うと、キーに対して異なる型の値を指定することもできる。たとえば、string型のキーに対して、値がstring | number型である場合:
interface MixedDictionary {
[key: string]: string | number; }
const userInfo: MixedDictionary = {
"name": "John", "age": 30, "country": "Japan" };
この場合、オブジェクトuserInfoのキーには文字列が使われ、値はstringまたはnumber型になる。
3. 型制限付きのインデックスシグネチャ
特定のプロパティを持ちながら、他のプロパティは柔軟に扱いたい場合にもindex signatureが有効。
interface Person {
namename: string;
// 他の任意のプロパティも許可
age: number; [key: string]: string | number;
}
const person: Person = {
name: "Alice",
age: 25,
city: "Tokyo", // 追加プロパティ
};
この例では、nameとageという固定プロパティに加え、他の任意のプロパティも追加できるようになっている。
注意点
インデックスシグネチャが指定された場合、その型以外のプロパティは持てない。
例えば、インデックスシグネチャでnumber型のプロパティを許可している場合、それ以外の型のプロパティは定義できない。
interface StrictDictionary {
[key: string]: number;
name: string; // エラー: 'string'は'number'に互換性がない
}
怖いやつとして
決まり切った型に、このインデックスシグネチャーを突っ込めば
型の追加が許容されることになる。誰でも追加可能で、見えない状態なのでプロパティの予測がつきにくくソースを追わないといけなくなることが多々出てくると思う。
動的にプロパティを作りたいときに限ってつけたしが分かるようにするのがいいだろうと個人的には思う。
interface Person {
name: string;
age: number;
metadata: {
[key: string]: string | number }; // 動的プロパティ
}
まとめ
index signatureは、オブジェクトのキーやプロパティ名が事前に決まっていない場合や、柔軟なキーと値を持つオブジェクトを扱うときに使える。
ご覧いただきありがとうございました。 サポートしていただいたお金は開発費にかけさせていただきます。