TypeScriptにおいて、「型」は非常に重要な概念です。今回は、型をよりスマートに効率的に書くための Mapped Types と ユーティリティ型 について扱おうと思います。
1. Mapped Typesとは?
Mapped Types とは、既存の型を基にして、新しい型を作成する仕組み です。これは、オブジェクトのプロパティを動的に変換する際に便利です。
例えば、すべてのプロパティを readonly
にしたい場合、通常はこのように記述すると思います。
type User = {
id: number;
name: string;
email: string;
}
type ReadonlyUser = {
readonly id: number;
readonly name: string;
readonly email: string;
}
Userのプロパティが今は3つですが、これが10, 20個と増えた際にすべてにreadonlyをつけるのは少し冗長で見映えが悪いです。
Mapped Types を使った場合、以下のようにより簡潔に記述できます。
type ReadonlyUser = {
readonly [K in keyof User]: User[K];
}
これで先ほどと同様、 User
型のすべてのプロパティが readonly
になりました。
2. 基本のMapped Types
1. すべてのプロパティをオプショナルにする (Partial<T>
)
type PartialUser = {
[K in keyof User]?: User[K]
}
ユースケース
- 一部のデータのみ更新したい時
- フォームの入力値を部分的に扱いたい時
2. すべてのプロパティを必須にする (Required<T>
)
type RequiredUser = {
[K in keyof User]-?: User[K]
}
ユースケース
- APIのレスポンスで全データが必ず存在する場合
3. すべてのプロパティを readonly
にする (Readonly<T>
)
type ReadonlyUser = {
readonly [K in keyof User]: User[K]
}
ユースケース
- オブジェクトの変更を防ぎたい時(Reactの
props
など)
3. TypeScriptのユーティリティ型を活用しよう!
TypeScriptには、開発を効率化する 便利なユーティリティ型 が色々用意されています。
1. Pick<T, K>
: 指定したプロパティだけを抽出
// Userからidとnameプロパティだけを抽出
type PickUser = Pick<User, "id" | "name">
ユースケース
- APIレスポンスで必要なプロパティだけを取得
2. Omit<T, K>
: 指定したプロパティを除外
// Userのうちemail以外のプロパティを抽出
type OmitUser = Omit<User, "email">
ユースケース
- ユーザー情報から個人情報を取り除いたデータを作成
3. Record<K, T>
: ユニオン型から特定のキーと型を持つオブジェクトを作成**
type Role = "admin" | "user" | "guest"
type RolePermissions = Record<Role, boolean>
// ↑はこれと同じ
type RolePermissions = {
admin: boolean;
user: boolean;
guest: boolean;
}
ユースケース
- ユーザーの権限管理(admin, user, guestのみに限定したい)
4. Extract<T, U>
: ユニオン型から指定した型にマッチするものだけを抽出
// Statusからactive, bannedだけを抽出
type Status = "active" | "inactive" | "banned"
type ActiveStatus = Extract<Status, "active" | "banned">
ユースケース
- 特定の条件に合致する型だけを扱う
5. Exclude<T, U>
: ユニオン型から指定した型を除外
// Statusからactive以外を抽出
type NonActiveStatus = Exclude<Status, "active">
ユースケース
- 必要のない型を削除
4. 応用編:高度なMapped Typesとユーティリティ型の組み合わせ
1. プロパティの型を変換する
例えば、すべてのプロパティを string
に変換する場合
type Stringify<T> = {
[K in keyof T]: string
}
type StringifiedUser = Stringify<User>
ユースケース
- 数値や日付データをすべて文字列として扱うケース
2. プロパティを一部変更する (Override<T, U>
の応用)
特定のプロパティだけ変更したい場合
type Override<T, U> = {
[K in keyof T]: K extends keyof U ? U[K] : T[K]
}
// `name` だけ型が `number` に
type UserWithNewName = Override<User, { name: number }>
ユースケース
- 一部のプロパティの型を変更して新しい型を作る
5. 最後に
今回取り上げたTypeScriptのMapped Types
とユーティリティ型
を使うと、柔軟で再利用性の高い型定義 を作ることができ、開発体験が向上します。
* 基本のMapped Types:Partial<T>
, Required<T>
, Readonly<T>
* 便利なユーティリティ型:Pick<T, K>
, Omit<T, K>
, Record<K, T>
, Extract<T, U>
, Exclude<T, U>
* 応用編:型の変換 (Stringify<T>
)、一部変更 (Override<T, U>
) など
これらを使いこなしてよいTypeScriptライフを!
参考サイト
採用拡大中!
アシストエンジニアリングでは一緒に働くフロントエンド、バックエンドのエンジニア仲間を募集しています!
少しでも興味ある方は、カジュアル面談からでもぜひお気軽にお話ししましょう!
お問い合わせはこちらから↓
https://official.assisteng.co.jp/contact/