📍

【TypeScript】型パズルで大活躍!! Mapped typeについて

2022/05/06に公開

どうもフロントエンドエンジニアのoreoです。

今回は、型パズルで大活躍するMapped typeに関して整理します。

1 Mapped typeについて

1-1 Mapped type

Mapped typeは、{ [P in K] : T }の様な形をとります。ユニオン型Kの構成要素Pに対して、Pというプロパティが型Tを持つオブジェクト型を生成してくれます。

具体的には、Mapped typeを使うと、下記のようにユニオン型EVASeriesの構成要素EVA0EVA1EVA2のプロパティを持ち、それらの型がstringであるオブジェクトPilotsを生成できます。

type EVASeries = "EVA0" | "EVA1" | "EVA2"

type Pilots = {
	[key in EVASeries] : string
}

Pilotsの型は👇の様になります。

type Pilots = {
	EVA0 : string;
	EVA1 : string;
	EVA2 : string;
}

const pilots:Pilots ={
	EVA0 : "rei",
	EVA1 : "shinji",
	EVA2 : "asuka",
}

1-2 Homomorphic mapped type

Homomorphic mapped typeは、{ [P in keyof T] : U }のような形をとります。オブジェクト型TのプロパティPに対して、型Uを持つようなオブジェクトを生成します。既存のオブジェクト型に対して、何かしらの加工を加えたい時に使用されるもので、ユーティリティ型のReadonly<T>では👇のように使用されています。

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

Readonly<T>では、例えば👇の様に、にオブジェクト型Pilotsを渡すと、Homomorphic mapped typeによって、プロパティであるEVA0EVA1EVA2Readonlystring型に変換してくれます。

type Pilots = {
	EVA0 : string;
	EVA1 : string;
	EVA2 : string;
}

type ReadonlyPilots = Readonly<Pilots>

ReadonlyPilotsは、👇の様になります。

type ReadonlyPilots = {
	readonly EVA0 : string;
	readonly EVA1 : string;
	readonly EVA2 : string;
}

因みに、Homomorphic mapped typeで使用されているGenerics型に関しては、こちらの記事をご参照ください。また、keyofを使用すると、オブジェクト型からプロパティ名の型を取得することができます。

2 最後に

ユーティリティ型を自分で作るとわかりますが、これらはオブジェクト型への変換やオブジェクト型を加工する際に大活躍する機能です。型安全にコードを書くには、押さえておきたい内容ですね。

3 参考

https://gihyo.jp/book/2022/978-4-297-12747-3

https://zenn.dev/qnighy/articles/dde3d980b5e386

https://typescriptbook.jp/reference/type-reuse/mapped-types

Discussion