Apr 8, 2022
4 mins read
今回もmattoさんのTypeScriptの動画をまとめていく
下記の様なEntity
の型を定義する。
type Entity =
| {
type: 'user'
}
| {
type: 'post'
}
| {
type: 'comment'
}
上記の型の各オブジェクトにidを追加したい。その時のコードは以下になる。
typeに応じたidのプロパティを追加している。
type EntityWithId =
| {
type: 'user'
userId: string
}
| {
type: 'post'
postId: string
}
| {
type: 'comment'
commentId: string
}
const result1: EntityWithId = {
type: 'post',
postId: '123'
}
const result2: EntityWithId = {
type: 'user',
userId: '123'
}
今回はEntityWithId
の部分をインデックスシグネチャを利用して作成していく。
実際のコードは以下になる。細かくみていく。
type EntityWithId = {
[ EntityType in Entity['type'] ]: {
type: EntityType
} & Record<`${EntityType}Id`, string>
}[Entity['type']]
[ EntityType in Entity['type'] ]
はルックアップ型とマップ型を使用しており、ルックアップ型を展開すると、以下になる。[ EntityType in "user" | "post" | "comment" ]
[Entity['type']]
の部分はユニオンのルックアップ型になっている。よって、["user" | "post" | "comment"]
になる。type EntityWithId = {
[ EntityType in "user" | "post" | "comment" ]: {
type: EntityType
}
}[Entity['type']]
Record
を除く以下の型の定義になる。type EntityWithId = {
[EntityType in Entity['type']]: {
type: EntityType
}
}[Entity['type']]
🔽
type EntityWithId = {
[ EntityType in "user" | "post" | "comment" ]: {
type: EntityType
}
}["user" | "post" | "comment"]
🔽
type EntityWithId = {
type: "user";
} | {
type: "post";
} | {
type: "comment";
}
Record<`${EntityType}Id`, string>
EntityType
はマップ型で文字列リテラル型になるため、"user" | "post" | "comment"
のどれかになる。
例えば、user
の場合は以下になる。Record型によって、オブジェクト型が定義できる。
Record<`${user}Id`, string>
🔽
{
userId: string
}
&
でインターセクション型(交差型)で定義しているRecord型のテンプレートリテラル型が使用できることが勉強になった。