TypeScriptでは、型の安全性を確保しながら柔軟なコードを記述するために「Mapped Types(マップドタイプ)」という機能が用意されています。Mapped Typesを活用することで、既存の型を変換し、新しい型を動的に生成することが可能になります。
本記事では、Mapped Typesの基本的な使い方から、実践的な活用例まで詳しく解説します。
[目次を開く]
Mapped Typesとは?
- Mapped Types(マップドタイプ)とは、TypeScriptの型システムの一部で、既存の型を基にして新しい型を動的に生成できる機能です。主に以下のような用途に活用されます。
- オブジェクト型のプロパティを一括変更
- 既存の型を元に派生型を作成
- 一貫性のある型変換の適用
例えば、オブジェクトのすべてのプロパティをオプショナルにしたり、読み取り専用にしたりすることが可能です。
Mapped Typesの基本構文
Mapped Typesの基本的な構文は以下の通りです。
type Mapped<T> = {
[P in keyof T]: T[P];
};
この構文のポイントは以下の通りです。
-
T
:元となる型 -
P in keyof T
:T
のすべてのプロパティをループ処理 -
T[P]
:プロパティの型をそのまま適用
※Tはジェネリクスです。おさらいしたい人は以下の記事を参照してください。
Mapped Typesの具体的な使い方
1. すべてのプロパティをオプショナルにする
オブジェクトの全プロパティをオプショナル(?
)にするには、Partial<T>
と同様のMapped Typesを作成できます。
type Optional<T> = {
[P in keyof T]?: T[P];
};
// 使用例
type User = {
name: string;
age: number;
};
type OptionalUser = Optional<User>;
// 結果:{ name?: string; age?: number; }
活用シーン:
APIからデータを取得する際、一部のデータが不足している可能性がある場合に便利です。
2. すべてのプロパティを読み取り専用にする
オブジェクトのプロパティを変更できないようにするには、readonly
修飾子を付与できます。
type Readonly<T> = {
readonly [P in keyof T]: T[P];
};
// 使用例
type Product = {
id: number;
title: string;
};
type ReadonlyProduct = Readonly<Product>;
// 結果:{ readonly id: number; readonly title: string; }
活用シーン:
設定オブジェクトなど、不変であるべきデータの扱いに適しています。
3. プロパティの型を変更する
既存の型のプロパティの型を変更したい場合、以下のように型変換が可能です。
type Stringify<T> = {
[P in keyof T]: string;
};
// 使用例
type Config = {
port: number;
secure: boolean;
};
type StringifiedConfig = Stringify<Config>;
// 結果:{ port: string; secure: string; }
活用シーン:
設定情報を文字列形式で扱いたい場合など、型を統一したいケースに有用です。
4. プロパティ名を変更する
プロパティ名を変更するためには、as
キーワードを使用します。
type RenameKeys<T> = {
[P in keyof T as `new_${string & P}`]: T[P];
};
// 使用例
type Person = {
name: string;
age: number;
};
type RenamedPerson = RenameKeys<Person>;
// 結果:{ new_name: string; new_age: number; }
活用シーン:
APIのレスポンスなどでキー名をカスタマイズする場合に役立ちます。
5. 一部のプロパティのみ変更
特定のプロパティのみを変更する場合、条件付き型(Conditional Types
)を組み合わせることで実現できます。
type MakeNullable<T, K extends keyof T> = {
[P in keyof T]: P extends K ? T[P] | null : T[P];
};
// 使用例
type Profile = {
username: string;
email: string;
};
type NullableProfile = MakeNullable<Profile, "email">;
// 結果:{ username: string; email: string | null; }
活用シーン:
特定のプロパティだけオプショナルやヌル許容にする場合に適しています。
実践的な応用例
1. APIレスポンスの型変換
APIから取得したデータを安全に扱うために、Mapped Typesを利用して適切な型変換を行うことができます。
type ApiResponse<T> = {
[P in keyof T]: T[P] | null;
};
type UserData = {
id: number;
name: string;
isActive: boolean;
};
type NullableUserData = ApiResponse<UserData>;
// 結果:{ id: number | null; name: string | null; isActive: boolean | null; }
2. フォームデータの型定義
ユーザー入力を処理する際、すべての値を文字列として扱う場合に便利です。
type FormData<T> = {
[P in keyof T]: string;
};
type FormInput = {
age: number;
email: string;
};
type StringFormInput = FormData<FormInput>;
// 結果:{ age: string; email: string; }
まとめ
TypeScriptのMapped Typesを活用することで、型の柔軟性を最大限に引き出し、保守性の高いコードを書くことができます。
特に、オプショナル化、読み取り専用化、型の変換など、さまざまなシチュエーションで役立ちます。
開発プロジェクトの効率化を図るために、ぜひMapped Typesを活用してみてください!