絶対に知るべきTypescriptのユーティリティ型
はじめに
この記事は以下の記事の和訳になります。なお、著者には許可をいただいております。
是非原文もご覧ください。
こんにちは、みなさん、今回この記事では、あなたの生活を楽にしてくれるいくつかの便利で重要なTypescriptのユーティリティ型について見ていこうと思います。
Typescriptのユーティリティ型は、他の新しい型を作成もしくは操作するために使うことができる、事前に定義されたジェネリック型になります。これらの型は全てのTypescriptのプロジェクトでグローバルに使うことができるので、依存関係を追加したりすることなく使うことができます。
目次
- Partial
- Required
- Omit
- Pick
- 複数のユーティリティ型を同時に使用する
- Readonly
- Mutable
- Exclude
- Extract
- ReturnType
- Parameters
- NonNullable
- Awaited
- AwaitedとReturnTypeの合わせ技
- おわりに
Partial
まずはじめに見ていくユーティリティ型は、Partial
で、その名の通り、全てを任意もしくは部分的にします。
こちらがユーティリティ型Partialの例です:
interface Person {
name: string;
age: number;
email: string;
}
// 'PartialPerson'という、Personの部分的なバージョンの型である、新しい型を定義します。
type PartialPerson = Partial<Person>;
// 以下と同じ:
// interface Person {
// name?: string | undefined;
// age?: number | undefined;
// email?: string | undefined;
// }
Required
Partial
とは反対のユーティリティ型で、全てを必須にします。
interface Person {
name?: string | undefined;
age?: number | undefined;
email?: string | undefined;
}
// 'RequiredPerson'という、'Person'の必須バージョンの新しい型を定義します。
type RequiredPerson = Required<Person>;
// 以下と同じ:
// interface Person {
// name: string;
// age: number;
// email: string;
// }
Omit
Omitユーティリティ型を使えば、規定の型から新しい型を作ることができます、がその型はいくつかのプロパティが削除されます。
interface User {
id: number;
name: string;
email: string;
age: number;
}
type UserWithoutEmail = Omit<User, 'email'>;
// 以下と同じ:
// interface Person {
// id: string;
// name: string;
// age: number;
// }
union
を渡すことによって、複数のプロパティを削除することもできます。
interface User {
id: number;
name: string;
email: string;
age: number;
}
type UserWithoutEmailAndName = Omit<User, 'email' | 'name'>;
// 以下と同じ:
// interface Person {
// id: string;
// age: number;
// }
Pick
Omit
と反対のユーティリティ型として、Pick
を使えば、規定の型からあるプロパティのセットだけを含む新しい型を作成することができます。
interface User {
id: number;
name: string;
email: string;
age: number;
}
type UserWithEmailAndName = Pick<User, 'email' | 'name'>;
// 以下と同じ:
// interface Person {
// name: string;
// email: string;
// }
複数のユーティリティ型を同時に使用する
複数のユーティリティ型を同時に使うこともできます。例えば:
interface User {
id: number;
name: string;
email: string;
age: number;
}
type PartialPick = Partial<Pick<User, 'email' | 'name'>>;
// 以下と同じ:
// interface Person {
// name?: string | undefined;
// email?: string | undefined;
// }
他の例:
interface User {
id: number;
name: string;
email: string;
age: number;
}
type OmitPartialPick = Omit<Partial<Pick<User, 'email' | 'name'>>, 'email'>;
// 以下と同じ:
// interface Person {
// name?: string | undefined;
// }
Readonly
Readonly
ユーティリティ型を使えば、規定の型のセットをreadonly
として作成することができ、初期化の後は全てのプロパティが変更不可能になります。
interface Person {
id: number;
name: string;
age: number;
}
type ReadonlyPerson = Readonly<Person>;
// 以下と同じ:
// interface Person {
// readonly id: number;
// readonly name: string;
// readonly age: number;
// }
const person: ReadonlyPerson = {
id: 1,
name: 'John',
age: 25
};
person.name = 'Mike'; // Error: Cannot assign to 'name' because it is a read-only property.
Mutable
Mutable
という型ヘルパーを作成し、読み込み専用の型を変更可能な型に変換することもできます。
interface Person {
readonly id: number;
readonly name: string;
readonly age: number;
}
// Mutableのシンタックスは以下の通り:
type Mutable<T> = {
-readonly [P in keyof T]: T[P];
};
type MutablePerson = Mutable<Person>;
// 以下と同じ:
// interface Person {
// id: number;
// name: string;
// age: number;
// }
Exclude
Exclude
ユーティリティ型を使えば、union
のメンバを削除した新しい型を作成することができます。
type NumberOrString = number | string;
type OnlyNumber = Exclude<NumberOrString, string>;
// 以下と同じ:
// type OnlyNumber = number;
const num: OnlyNumber = 5;
const str: OnlyNumber = 'hello'; // Error: Type '"hello"' is not assignable to type 'number'.
ユニオンの複数のメンバを削除することもできます。
type NumberStringOrBoolean = number | string | boolean;
type OnlyBoolean = Exclude<NumberStringOrBoolean, string | number>;
// same as:
// type OnlyBoolean = boolean;
Extract
Exclude
の反対のユーティリティ型として、Extract
型を使えば、ユニオン型から一つもしくは複数の項目を抽出することができます:
type NumberOrString = number | string | boolean;
type OnlyNumber = Extract<NumberOrString, number>;
// 以下と同じ:
// type OnlyNumber = number;
ReturnType
ReturnType
ユーティリティ型を使えば、関数の戻り値の型を抽出することができます。関数の型を引数として渡し、その関数の戻り値の型を返します。
function add(a: number, b: number): number {
return a + b;
}
type AddReturnType = ReturnType<typeof add>;
// type AddReturnType = number;
// ---
function addStr(a: string, b: string): string{
return a + b;
}
type AddReturnType2 = ReturnType<typeof addStr>;
// type AddReturnType2 = string;
Parameters
Parameters
ユーティリティ型を使えば、関数の引数の型を抽出することができるようになります。
function add(a: number, b: string, c:boolean): string {
return a + b;
}
type AddReturnType = Parameters<typeof add>;
// type AddReturnType = [a: number, b: string, c:boolean];
NonNullable
NonNullable
ユーティリティ型を使えば、与えられた型から、null
とundefined
を除去した新しい型を作成することができるようになります。
type NullableString = string | null | undefined;
type NonNullableString = NonNullable<NullableString>;
// type NonNullableString = string;
const str1: NullableString = null;
const str2: NonNullableString = 'hello';
const str3: NonNullableString = null; // Error: Type 'null' is not assignable to type 'string'.
Awaited
Awaited
ユーティリティ型を使えば、promise
もしくはawait
を使う他の型の、resolveされた後の型を抽出することができます。
type promiseNumber = Promise<number>
type justNumber = Awaited<Promise<number>>
// type justNumber = number
AwaitedとReturnTypeの合わせ技
こちらはReturnType
とAwaited
を同時に使う例です:
async function fetchData(): Promise<string> {
// fetch data from API and return a string
}
type ResolvedResult = Awaited<ReturnType<typeof fetchData>>;
// type ResolvedResult = string
この例では、stringのPromise
(Promise<string>
)を返す、非同期関数を定義します。そして、ReturnType
を使い、fetchData
の戻り値の型を抽出し、Awaited
の引数としてそれを渡し、promiseがresolveされた時の型を抽出しています。
おわりに
世界中の開発者達に非常によく使われているTypescriptのユーティリティ型のいくつかを紹介しました。これらはあなたのコードをクリーンにし、型をより表現豊かに、そして簡潔にすることができるでしょう。この記事があなたの役に立つことを願い、もし他に重要なユーティリティ型を見逃していた場合、コメントで教えてくれると助かります。記事を読んでいただきありがとうございます。次の記事でお会いしましょう🐼。
Discussion