メインコンテンツまでスキップ

Mapped type

インデックス型では設定時はどのようなキーも自由に設定できてしまい、アクセス時は毎回undefinedかどうかの型チェックが必要です。入力の形式が決まっているのであればMapped typeの使用を検討できます。

Mapped typeは主にユニオン型と組み合わせて使います。先ほどシステムがサポートする言語を定義しました。

typescript
type SystemSupportLanguage = "en" | "fr" | "it" | "es";
typescript
type SystemSupportLanguage = "en" | "fr" | "it" | "es";

これをインデックス型と同じようにキーの制約として使用することができます。

typescript
type Butterfly = {
[key in SystemSupportLanguage]: string;
};
typescript
type Butterfly = {
[key in SystemSupportLanguage]: string;
};

このようにButterflyを定義するとシステムがサポートしない言語、ここではdeが設定、使用できなくなります。

typescript
const butterflies: Butterfly = {
en: "Butterfly",
fr: "Papillon",
it: "Farfalla",
es: "Mariposa",
de: "Schmetterling",
};
// Object literal may only specify known properties, and 'de' does not exist in type 'Butterfly'.
typescript
const butterflies: Butterfly = {
en: "Butterfly",
fr: "Papillon",
it: "Farfalla",
es: "Mariposa",
de: "Schmetterling",
};
// Object literal may only specify known properties, and 'de' does not exist in type 'Butterfly'.

プロパティを読み取り専用にするreadonlyをそのオブジェクトのすべてのプロパティに適用するReadonly<T>というユーティリティ型があります。他にもユーティリティ型はありますが、それらについては専門のページがありますのでここでは割愛します。

Readonly<T>もこの機能で実現されています。Readonly<T>は次のように実装されています。

typescript
type Readonly<T> = {
readonly [P in keyof T]: T[P];
};
typescript
type Readonly<T> = {
readonly [P in keyof T]: T[P];
};

keyof Tという見慣れない表現が登場しましたが、これはオブジェクトのキーをユニオン型に変更するものだと解釈してください。keyofの詳細は型演算子をご覧ください。

インデックス型と異なるところ#

Mapped typeはインデックス型と異なりsymbol型もキーにすることができます。

typescript
type Identifier = symbol | 1;
type Sample = {
[P in Identifier]: string;
};
const sample: Sample = {
1: 'pork';
[Symbol('thick')]: 'thin';
};
typescript
type Identifier = symbol | 1;
type Sample = {
[P in Identifier]: string;
};
const sample: Sample = {
1: 'pork';
[Symbol('thick')]: 'thin';
};