こんにちは、フロントエンドエンジニアのまさにょんです。
今回は、TypeScriptにおけるMapped Typesの使い方について解説して行きます。
以前に説明したIndex-Signature(インデックス・シグネチャー)も説明の中で出てきますので、そちらの理解がまだな方はあわせて以下の記事も参照してみてください。
Mapped Typesとは何か?
こちらの説明が分かりやすかったので引用します。
Mapped Types(マップ型)とはある型をもとに新たな型を定義する際に利用される型のことをいいます。
すでに定義されているUnion型やオブジェクトのキーを再利用(マップ)して新しい型を定義するため、Mapped Typesという名前がつけられています。
Mapped Typesを利用することにより、オブジェクトに設定できるプロパティを指定できます。
引用元: Mapped Types(マップ型)の概要と利用方法まとめ
Mapped-Typesでは、すでに定義されているUnion型やオブジェクトのキーを使って、新しい型のkey名を定義することができます。
これは、いわゆる「型」の再利用であり、関連付け(Map)だと言えます。
基本構文は、こういった形になります。
type 型変数名 = { [ key-変数 in keyに関連付ける値 ] : valueの型 }
それでは、実際にCodeを観て行きましょう。
// < Mapped-Types-基本構文 >
// type 型変数名 = { [ key-変数 in keyに関連付ける値 ] : valueの型 }
// 1. Mapped-Types
type MappedTypes = {
[key in "firstName" | "lastName"]: string;
};
// < 出力結果 >
// type MappedTypes = {
// firstName: string;
// lastName: string;
// }
// "firstName" と "lastName" をkey名に持ち、valueの型はstringの「型」ができあがりました。
// 2. interfaceでは、errorが発生する。
interface ErrorMappedTypes {
[key in "firstName" | "lastName"]: string;
};
// A computed property name in an interface must refer to an expression whose type is a literal type or a 'unique symbol' type.
// インターフェイスで計算されたプロパティ名は、タイプがリテラルタイプまたは「一意のシンボル」タイプである式を参照する必要があります。
このように、key名を指定して、新しい型を作成できるのが、Mapped-Typesの特徴です。
もちろん、key名を指定すると言うことは、Mapped-Typesを使用するTargetはObjectだと言うことがわかります。
ちなみに、Mapped-Typesは、interfaceでは使えずtype-aliasでのみ使えるようです。
interfaceでは、a literal type or a ‘unique symbol’ typeしか使えないとErrorで注意されます。
Index-SignatureとMapped-Typesの比較
Index-Signature(インデックス・シグネチャー)とMapped-Typesの違いを考えて行きましょう。
Index-Signature(インデックス・シグネチャー)では、「key-変数」の型はstring、number、symbolのいずれかの型を指定することができます。
それに対して、Mapped-Typesでは、通常のIndex-Signatureで使用することのできないLiteral-Union-Typesなどが使えます。
すなわち、より「具体的なkey-名」(Literal-Type)を設定したいときにMapped-Typesは役立つと言うことです。
// 1. Index-Signatureでは、key名の型を指定して、変数化できる記法
type IndexSignature = {
[key : string] : string;
}
// 出力結果
// type IndexSignature = {
// [key: string]: string;
// }
// Index-Signatureでは、key名を自由に設定できる!
const Object1: IndexSignature = {
firstName: '東京のもも',
lastName: 'Momoちゃん',
like: 'maguro'
}
// 2. Mapped-Typesでは、key名にLiteral-Union型などを指定して、key名に制約を課すことができる。
type MappedTypes = {
[key in "firstName" | "lastName"]: string;
};
// 出力結果
// type MappedTypes = {
// firstName: string;
// lastName: string;
// }
const Object2: MappedTypes = {
firstName: 'グンマー帝国のロボ',
lastName: 'ロボ玉',
like: 'ひまたね' // error
}
まとめ
- Index-Signatureでkey名に指定できる「型」は、string、number、symbolのみ。
- Mapped-Typesでは、key名にLiteral-Union型やObject-Keyを再利用(Map)して、「型」をkey名に定義できる。
- Mapped-Typesでは、key名に特定のLiteral-TypeをMapping(関連付け)することができる。
- Mapped-Typesでは、type-ailiasでのみ使用可能。interfaceでは使用できない。
TypeScript書籍
参考・引用
1. Mapped Types(マップ型)の概要と利用方法まとめ
2. Mapped type
3. オブジェクトのkeyをtypeで指定する(Mapped types)
4. TypeScriptでMapped Typesを使ってきれいなインターフェースを作る話