TypeScriptにおけるユーティリティ型

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>を使うことで、nameageも必須のプロパティとして扱われます。

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はキーの型(stringnumberなど)、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>を使うことで、オブジェクト型の中から特定のプロパティだけを取り出して、新しい型として扱うことができます。例えば、上記ではidnameだけを取り出しています。

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>は、nullundefinedを除外した型を作成します。オプション型からこれらの値を除外したい場合に役立ちます。

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>は、nullundefinedを除外するので、値が存在することを保証できます。

結論

TypeScriptのユーティリティ型は、型定義をより簡潔かつ柔軟に行うための強力なツールです。PartialRequiredReadonlyRecordなどの基本的なユーティリティ型を理解し、適切に活用することで、コードの再利用性や保守性を向上させることができます。これらの型を使いこなすことで、より強力で安全な型定義を実現し、効率的な開発が可能になります。

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チャンネルもご覧ください。

YouTube Video