TypeScriptオブジェクトの型制約
TypeScriptでは、オブジェクトのインデックス付きメンバーの型を強制することができます。これにより、コードの型安全性と読みやすさを向上させることができます。
インデックス付きメンバーの型を強制するには、次のようにします。
インデックスシグネチャを使用する:
interface IndexedObject { [index: string]: number; } const indexedObject: IndexedObject = { foo: 1, bar: 2 }; indexedObject.foo = "hello"; // エラー: 型 'string' は 'number' に割り当てられません
インデックスシグネチャは、オブジェクトのインデックスがどのような型であるか、およびインデックスに対応する値がどのような型であるかを指定します。上記の例では、インデックスは
string
型であり、値はnumber
型であることを指定しています。インデックス付きアクセス演算子を使用する:
interface IndexedObject { [index: number]: string; } const indexedObject: IndexedObject = { 0: "foo", 1: "bar" }; indexedObject["foo"] = "hello"; // エラー: 型 'string' は 'number' に割り当てられません
インデックス付きアクセス演算子を使用して、オブジェクトのインデックス付きメンバーにアクセスすることができます。このとき、インデックスの型が正しいかどうかがチェックされます。
keyof
型を使用してインデックスシグネチャを定義する:interface IndexedObject { [index in keyof IndexedObject]: string; } const indexedObject: IndexedObject = { foo: "hello", bar: "world" }; indexedObject.foo = 1; // エラー: 型 'number' は 'string' に割り当てられません
keyof
型を使用すると、オブジェクトのすべてのキーの型を指定することができます。これにより、インデックスシグネチャをより簡潔に書くことができます。
interface IndexedObject {
[index: string]: number;
}
const indexedObject: IndexedObject = {
foo: 1,
bar: 2
};
indexedObject.foo = "hello"; // エラー: 型 'string' は 'number' に割り当てられません
- 効果
indexedObject
のインデックス付きメンバーはすべてnumber
型でなければなりません。これにより、誤った型を割り当てることを防ぎます。 - 説明
インデックスシグネチャ[index: string]: number;
を使用して、オブジェクトのインデックスがstring
型であり、対応する値がnumber
型であることを指定しています。
interface IndexedObject {
[index: number]: string;
}
const indexedObject: IndexedObject = {
0: "foo",
1: "bar"
};
indexedObject["foo"] = "hello"; // エラー: 型 'string' は 'number' に割り当てられません
- 効果
インデックスがnumber
型であることを強制し、誤った型を割り当てることを防ぎます。 - 説明
インデックス付きアクセス演算子indexedObject["foo"]
を使用して、オブジェクトのインデックス付きメンバーにアクセスしています。
interface IndexedObject {
[index in keyof IndexedObject]: string;
}
const indexedObject: IndexedObject = {
foo: "hello",
bar: "world"
};
indexedObject.foo = 1; // エラー: 型 'number' は 'string' に割り当てられません
- 説明
keyof IndexedObject
を使用して、オブジェクトのすべてのキーの型を指定しています。
マッピング型 (Mapped Types)
マッピング型を使用すると、既存の型の各プロパティを新しい型に変換することができます。これにより、インデックス付きメンバーの型を強制することができます。
type IndexedObject<T> = {
[P in keyof T]: T[P];
};
const indexedObject: IndexedObject<{ foo: string; bar: number }> = {
foo: "hello",
bar: 123
};
- 効果
indexedObject
のインデックス付きメンバーの型は、T
のプロパティの型と一致するよう強制されます。 - 説明
マッピング型IndexedObject<T>
を定義し、既存の型T
の各プロパティをそのままコピーしています。
インターセクション型 (Intersection Types)
interface StringIndexedObject {
[index: string]: string;
}
interface NumberIndexedObject {
[index: number]: number;
}
type CombinedIndexedObject = StringIndexedObject & NumberIndexedObject;
const indexedObject: CombinedIndexedObject = {
foo: "hello",
1: 123
};
- 効果
indexedObject
のインデックス付きメンバーは、string
型またはnumber
型でなければなりません。 - 説明
インターセクション型CombinedIndexedObject
を定義し、StringIndexedObject
とNumberIndexedObject
の共通部分を指定しています。
条件型 (Conditional Types)
type IndexedObject<T extends string | number> = {
[P in T]: string;
};
const indexedObject: IndexedObject<"foo" | "bar"> = {
foo: "hello",
bar: "world"
};
- 説明
条件型IndexedObject<T>
を定義し、T
がstring
またはnumber
型である場合に、インデックス付きメンバーの型をstring
型に強制しています。
typescript