Mapped type
インデックス型では設定時はどのようなキーも自由に設定できてしまい、アクセス時は毎回undefinedかどうかの型チェックが必要です。入力の形式が決まっているのであればMapped typeの使用を検討できます。
Mapped typeは主にユニオン型と組み合わせて使います。先ほどシステムがサポートする言語を定義しました。
typescripttype SystemSupportLanguage = "en" | "fr" | "it" | "es";
typescripttype SystemSupportLanguage = "en" | "fr" | "it" | "es";
これをインデックス型と同じようにキーの制約として使用することができます。
typescripttype Butterfly = {[key in SystemSupportLanguage]: string;};
typescripttype Butterfly = {[key in SystemSupportLanguage]: string;};
このようにButterflyを定義するとシステムがサポートしない言語、ここではdeが設定、使用できなくなります。
typescriptconst 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'.
typescriptconst 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>は次のように実装されています。
typescripttype Readonly<T> = {readonly [P in keyof T]: T[P];};
typescripttype Readonly<T> = {readonly [P in keyof T]: T[P];};
keyof Tという見慣れない表現が登場しましたが、これはオブジェクトのキーをユニオン型に変更するものだと解釈してください。keyofの詳細は型演算子をご覧ください。
インデックス型と異なるところ#
Mapped typeはインデックス型と異なりsymbol型もキーにすることができます。
typescripttype Identifier = symbol | 1;type Sample = {[P in Identifier]: string;};const sample: Sample = {1: 'pork';[Symbol('thick')]: 'thin';};
typescripttype Identifier = symbol | 1;type Sample = {[P in Identifier]: string;};const sample: Sample = {1: 'pork';[Symbol('thick')]: 'thin';};