TypeScriptにおけるユーティリティ型
この記事ではTypeScriptにおけるユーティリティ型について説明します。
YouTube Video
TypeScriptにおけるユーティリティ型
TypeScriptのユーティリティ型(Utility Types)は、既存の型を基に新しい型を作成するための便利なツールです。これにより、型定義をより柔軟に行うことができ、コードの再利用性を高めることができます。ここでは、よく使われるユーティリティ型について詳しく説明し、それぞれの使い方をサンプルコードと共に解説します。
Partial<T>
Partial<T>
は、オブジェクト型のすべてのプロパティをオプション(undefined
を許容)にします。元の型が持つプロパティの一部のみを使用したい場合に便利です。
1interface User {
2 id: number;
3 name: string;
4 age: number;
5}
6
7function updateUser(user: Partial<User>) {
8 console.log(user);
9}
10
11updateUser({ name: "Alice" }); // Updates only 'name'
- 上記の例では、
Partial<User>
を使用することで、User
型のすべてのプロパティがオプショナルになっています。そのため、updateUser
関数では一部のプロパティだけを渡すことができます。
Required<T>
Required<T>
は、オプションのプロパティも含めてすべてのプロパティを必須にします。すでにオプションとなっているプロパティを必須に変換したい場合に使用します。
1interface User {
2 id: number;
3 name?: string;
4 age?: number;
5}
6
7function createUser(user: Required<User>) {
8 console.log(user);
9}
10
11// createUser({ id: 1 }); // Error: 'name' and 'age' are required
12createUser({ id: 1, name: "Alice", age: 25 });
Required<User>
を使うことで、name
やage
も必須のプロパティとして扱われます。
Readonly<T>
Readonly<T>
は、オブジェクトのすべてのプロパティを読み取り専用にします。これにより、オブジェクトの値を変更できなくなります。
1interface User {
2 id: number;
3 name: string;
4}
5
6const user: Readonly<User> = {
7 id: 1,
8 name: "Alice"
9};
10
11// user.id = 2; // Error: 'id' is read-only
12console.log(user);
Readonly<T>
を使うことで、オブジェクトのプロパティが変更されないように保護できます。開発中にデータが誤って変更されることを防ぎたい場合に有効です。
Record<K, T>
Record<K, T>
は、キーと値の型を指定してマップ型を作成します。K
はキーの型(string
やnumber
など)、T
は値の型です。
1type Roles = "admin" | "user" | "guest";
2interface ReadWritePermissions {
3 read: boolean;
4 write: boolean;
5}
6
7const rolePermissions: Record<Roles, ReadWritePermissions> = {
8 admin: { read: true, write: true },
9 user: { read: true, write: false },
10 guest: { read: false, write: false },
11};
12
13console.log(rolePermissions);
Record<K, T>
は、キーと値のペアを定義したいときに便利です。上記の例では、ユーザーの役割に応じた権限を定義しています。
Pick<T, K>
Pick<T, K>
は、オブジェクト型から指定したプロパティだけを抜き出します。必要なプロパティのみを取り出して新しい型を作成できます。
1interface User {
2 id: number;
3 name: string;
4 age: number;
5}
6
7type UserSummary = Pick<User, "id" | "name">;
8
9const summary: UserSummary = {
10 id: 1,
11 name: "Alice"
12};
13
14console.log(summary);
Pick<T, K>
を使うことで、オブジェクト型の中から特定のプロパティだけを取り出して、新しい型として扱うことができます。例えば、上記ではid
とname
だけを取り出しています。
Omit<T, K>
Omit<T, K>
は、オブジェクト型から指定したプロパティを除外します。これはPick
の逆の操作です。
1interface User {
2 id: number;
3 name: string;
4 age: number;
5 email: string;
6}
7
8type UserWithoutEmail = Omit<User, "email">;
9
10const userWithoutEmail: UserWithoutEmail = {
11 id: 1,
12 name: "Alice",
13 age: 25
14};
15
16console.log(userWithoutEmail);
Omit<T, K>
を使うことで、指定したプロパティを除外して新しい型を作成できます。上記の例では、email
プロパティが除外されています。
Exclude<T, U>
Exclude<T, U>
は、ユニオン型T
から型U
を除外した新しい型を作成します。特定の型を取り除きたい場合に使用します。
1type Status = "active" | "inactive" | "pending";
2type ExcludedStatus = Exclude<Status, "pending">;
3
4const userStatus: ExcludedStatus = "active"; // "pending" is excluded, so it cannot be chosen
5console.log(userStatus);
Exclude<T, U>
を使用すると、ユニオン型の中から不要な型を取り除くことができます。上記の例では、"pending"
が除外されているため、"active"
や"inactive"
のみが選択できます。
Extract<T, U>
Extract<T, U>
は、ユニオン型T
の中から型U
と一致する部分を抽出します。特定の型のみを抽出したい場合に便利です。
1type Status = "active" | "inactive" | "pending";
2type ActiveStatus = Extract<Status, "active" | "pending">;
3
4const userStatus: ActiveStatus = "active"; // "inactive" cannot be chosen
5console.log(userStatus);
Extract<T, U>
は、Exclude
の逆の操作を行います。上記の例では、"active"
と"pending"
だけが選択できるようになっています。
NonNullable<T>
NonNullable<T>
は、null
やundefined
を除外した型を作成します。オプション型からこれらの値を除外したい場合に役立ちます。
1type UserName = string | null | undefined;
2type ValidUserName = NonNullable<UserName>;
3
4const userName: ValidUserName = "Alice"; // null and undefined cannot be chosen
5console.log(userName);
NonNullable<T>
は、null
やundefined
を除外するので、値が存在することを保証できます。
結論
TypeScriptのユーティリティ型は、型定義をより簡潔かつ柔軟に行うための強力なツールです。Partial
、Required
、Readonly
、Record
などの基本的なユーティリティ型を理解し、適切に活用することで、コードの再利用性や保守性を向上させることができます。これらの型を使いこなすことで、より強力で安全な型定義を実現し、効率的な開発が可能になります。
TypeScriptのkeyof
演算子
TypeScriptのkeyof
演算子は、オブジェクト型のすべてのプロパティ名を取得するために使用されます。この演算子を使うと、オブジェクト型のキーをユニオン型として取得できます。これは、型安全なコードを書くために非常に便利です。
基本的な使い方
1interface Person {
2 name: string;
3 age: number;
4 email: string;
5}
6
7// Use keyof to get the property names of Person
8type PersonKeys = keyof Person; // "name" | "age" | "email"
使用例
関数の引数における利用
keyof
を使用して、オブジェクトの特定のプロパティに基づく型を持つ関数を定義できます。
1function getProperty<T, K extends keyof T>(obj: T, key: K): T[K] {
2 return obj[key];
3}
4
5const person: Person = { name: "Alice", age: 30, email: "alice@example.com" };
6const userName = getProperty(person, "name"); // type is string
7const age = getProperty(person, "age"); // type is number
8
9console.log("Name:", userName);
10console.log("Age:", age);
- この関数は、指定したキーに基づいてオブジェクトから型安全にプロパティを取得します。
型制約の強化
keyof
を使用することで、関数が受け取るキーが正しいかをコンパイル時にチェックできます。
1// Passing an invalid property name results in an error
2const invalid = getProperty(person, "invalidKey"); // Error
- このコードは、存在しないプロパティ名を指定するとコンパイル時にエラーになることを示しています。
まとめ
keyof
演算子は、オブジェクト型のすべてのプロパティ名を取得するために使用されます。- ユニオン型としてプロパティ名を取得し、型安全なコードを実現できます。
- 関数の引数に使用することで、正しいプロパティ名だけを受け取るように制約をかけることができます。
このように、keyof
演算子はTypeScriptでの型安全性を高め、より堅牢なコードを書く手助けをします。
YouTubeチャンネルでは、Visual Studio Codeを用いて上記の記事を見ながら確認できます。 ぜひYouTubeチャンネルもご覧ください。