TypeScriptでよく使う5つのユーティリティ型(utility types)の使い方
TypeScriptのコードを読んでいると、突然こんな記法が出てきて「?」となることがありませんか。
Partial<User> とか Pick<User, 'id' | 'name'> って何? 見たことない書き方だけど…
この記事では、TypeScriptのユーティリティ型の基本的な考え方と、実際によく使う5つの型(Partial・Readonly・Pick・Omit・Record)の使い方をまとめて解説します。
この記事は次のような方におすすめです。
- ユーティリティ型という言葉は聞いたことがあるが、何なのかよくわからない方
- Partial や Pick がコードに出てきて、意味を調べたい方
- PickとOmitの使い分けに迷っている方
- たくさんあるユーティリティ型のうち、まず何を覚えるべきか知りたい方
この記事を読むと、ユーティリティ型の考え方と、よく使う5型の書き方・使いどころがひと通りわかります。「全部覚えなきゃ」とプレッシャーを感じている方も、まずここで紹介する5つを押さえておけば十分です。
それでは、順を追って詳しく見ていきましょう!
- 未経験で後悔したくない
【実体験】未経験からITエンジニアに転職して後悔した話|4社経験してわかった「最初の選択ミス」 - 年収が低くて不安
4年間ずっと年収260万だったエンジニアが、転職で510万になるまでの全記録
ユーティリティ型とは — 既存の型を「加工」して使う仕組み
ユーティリティ型とは、すでに定義した型をもとに、別の型を作り出すための仕組みです。
少しイメージしにくいかもしれないので、例で考えてみます。
たとえば、こんな User 型があるとします。
interface User {
id: number;
name: string;
email: string;
}
このとき「ユーザーの更新処理では、変更しないフィールドもあるから、全プロパティを任意にしたい」という場面が出てきます。そのたびに別の型を手書きするのは手間ですし、元の型を変えたときに修正箇所が増えてしまいます。
そこでユーティリティ型の出番です。
type PartialUser = Partial<User>;
// { id?: number; name?: string; email?: string; } と同じ意味になる
Partial<User> と書くだけで、User の全プロパティを任意(省略可能)にした新しい型を作れます。元の型を「引数」として渡すと、加工済みの型が返ってくる——そういうイメージで捉えると理解しやすいです。
<User> や <T> の記法(ジェネリクス)がよくわからない方は、先にこちらの記事を読んでおくとスムーズです。
この記事で扱う5つのユーティリティ型
TypeScriptには十数種類のユーティリティ型が標準で用意されています。ただ、全部を一度に覚える必要はありません。
この記事では、実際のコードで出てくる頻度が高い5つに絞って説明します。
| ユーティリティ型 | 何をするか |
|---|---|
Partial<T> |
全プロパティを任意(省略可能)にする |
Readonly<T> |
全プロパティを変更禁止にする |
Pick<T, K> |
指定したプロパティだけを取り出す |
Omit<T, K> |
指定したプロパティだけを除外する |
Record<K, T> |
キーと値の型を指定してオブジェクト型を作る |
この5つを理解しておくだけで、実際のコードで「なんだこれ?」と詰まる場面がかなり減ります。
Partial — 全プロパティを「任意」に変換する
書き方と基本的な使い方
Partial<T> は、型 T のすべてのプロパティを省略可能(? 付き)に変換します。
interface User {
id: number;
name: string;
email: string;
}
type PartialUser = Partial<User>;
// 結果: { id?: number; name?: string; email?: string; }
Partial<User> とするだけで、全プロパティが任意になった型を作れます。元の User は変わらないので、必要に応じて使い分けられます。
どんな場面で役立つか
「全部の値が揃っていなくても受け取りたい」という場面で活躍します。
たとえば、ユーザー情報の一部だけを更新する関数を書くとき。全フィールドを必須にしてしまうと、名前だけ変えたいときでも id や email も渡さないといけません。
// 更新したいフィールドだけ受け取れる関数
function updateUser(id: number, fields: Partial<User>) {
// fields.name だけ来ることも、fields.email だけ来ることもある
console.log(id, fields);
}
updateUser(1, { name: "田中" }); // OK
updateUser(1, { email: "t@example.com" }); // OK
Partial<User> を使うことで、「渡したいフィールドだけ渡せる関数」を型安全に書けます。フォームの入力途中データや、設定オブジェクトの部分更新などでよく見かける使い方です。
Readonly — 全プロパティを「変更禁止」にする
書き方と基本的な使い方
Readonly<T> は、型 T のすべてのプロパティを読み取り専用にします。値を代入しようとするとコンパイルエラーになります。
interface Config {
apiUrl: string;
timeout: number;
}
const config: Readonly<Config> = {
apiUrl: "https://example.com",
timeout: 3000,
};
config.apiUrl = "https://other.com"; // エラー!変更できない
Readonly<Config> とすることで、オブジェクトのプロパティをうっかり書き換えてしまうミスをコンパイル時に防げます。
どんな場面で役立つか
「絶対に変えてはいけない値を定義したい」という場面で使います。
アプリの設定値や定数オブジェクトなど、「一度決めたら変えない」ものに使うと、意図しない変更をコードレベルで防げます。
Pick — 必要なプロパティだけを取り出す
書き方と基本的な使い方
Pick<T, K> は、型 T の中から、K に指定したプロパティだけを取り出した新しい型を作ります。
interface User {
id: number;
name: string;
email: string;
password: string;
}
type PublicUser = Pick<User, "id" | "name">;
// 結果: { id: number; name: string; }
Pick<User, "id" | "name"> とすることで、id と name だけを持つ型が作れます。ユニオン型(|)で複数のプロパティ名を指定できます。
どんな場面で役立つか
「元の型から一部だけ使いたい」という場面で活躍します。
たとえば、APIのレスポンスとして受け取った型が大きい場合に、UI表示に必要なフィールドだけを取り出した型として使うケースが典型的です。
// 一覧画面ではidとnameだけ使いたい
type UserListItem = Pick<User, "id" | "name">;
また、password のような秘匿情報を含む型から、外部に渡せる安全な型を作るときにも使えます。
Omit — 不要なプロパティだけを除外する
書き方と基本的な使い方
Omit<T, K> は、型 T の中から、K に指定したプロパティだけを除外した新しい型を作ります。Pick とは逆の発想です。
interface User {
id: number;
name: string;
email: string;
password: string;
}
type SafeUser = Omit<User, "password">;
// 結果: { id: number; name: string; email: string; }
Omit<User, "password"> とすることで、password だけを取り除いた型が作れます。
Omitの使いどころと、Pickとの使い分け
「元の型からいくつかのプロパティだけを除きたい」という場面で使います。先ほどの Pick と用途が似ているので、どちらを使えばいいか迷う方も多いです。
判断の軸はシンプルです。
- 除外したいプロパティが少ないとき Omit
- 取り出したいプロパティが少ないとき Pick
// passwordだけ除きたい → 除外1つ → Omitが自然
type SafeUser = Omit<User, "password">;
// idとnameだけ欲しい → 取り出しが2つ → どちらでも書けるが、Pick が意図を伝えやすい
type PublicUser = Pick<User, "id" | "name">;
たとえば User に10個のプロパティがあって、そのうち1つだけ除きたい場合、Pick で残り9つを列挙するのは大変です。そういうときは Omit を使うと簡潔に書けます。
フォームの「新規作成」型を作るときも Omit がよく使われます。データベースが自動生成する id だけ除いて「入力用の型」を作るケースです。
// 新規作成時はidが不要(DBが自動生成するため)
type CreateUserInput = Omit<User, "id">;
Record — キーと値の型をまとめてオブジェクト型を作る
書き方と基本的な使い方
Record<Keys, Type> は、キーの型と値の型を指定してオブジェクト型を作るユーティリティ型です。これまでの4つとは少し性格が異なり、既存の型を加工するというより、型を新しく作り出すイメージです。
type StatusMessage = Record<string, string>;
// 結果: { [key: string]: string; }
const messages: StatusMessage = {
success: "処理が完了しました",
error: "エラーが発生しました",
loading: "読み込み中...",
};
Record<string, string> とすると、「キーが文字列、値も文字列」のオブジェクト型になります。
どんな場面で役立つか
「決まったキーに対して値をマッピングするオブジェクトを作りたい」という場面で特に便利です。
キーにユニオン型を使うと、定義したキー以外が入るとエラーになるため、より型安全に書けます。
type Status = "success" | "error" | "loading";
type StatusMessage = Record<Status, string>;
const messages: StatusMessage = {
success: "処理が完了しました",
error: "エラーが発生しました",
loading: "読み込み中...",
// ここに定義外のキーを追加するとエラーになる
};
Status というユニオン型をキーに使うことで、「定義されたステータスに対してメッセージが必ず存在する」という保証が得られます。
ユーティリティ型を使うときの注意点
Partialはネストしたオブジェクトには効かない
Partial の挙動でつまずきやすいのが、ネストされたオブジェクトには適用されないという点です。
interface Address {
city: string;
zip: string;
}
interface User {
name: string;
address: Address;
}
type PartialUser = Partial<User>;
// 結果: { name?: string; address?: Address; }
// address自体は省略できるが、address.city や address.zip は任意にならない!
Partial<User> は1階層のプロパティしか任意にしません。ネストされたオブジェクトの内部プロパティまで全部任意にしたい場合は、「Deep Partial」と呼ばれるカスタム型を自前で用意する方法があります。
Pickは存在しないキーを指定するとエラーになる(Omitは無視される)
Pick で指定するプロパティ名は、元の型に存在するものでなければなりません。存在しないキーを指定するとコンパイルエラーになります。
type User = { id: number; name: string };
type WrongPick = Pick<User, "phone">; // エラー!'phone'はUserに存在しない
一方、Omit は存在しないキーを指定してもエラーにはなりません。指定したキーが元の型にない場合、そのキーは単に無視されて元の型がそのまま返ります。
type User = { id: number; name: string };
type WrongOmit = Omit<User, "phone">; // エラーにならず、Userと同じ型になる
タイポに気づかないまま使ってしまう可能性があるので、Omit でキー名を指定するときは特に注意してください。
【付録】さらに学びを深めるためのリソース
さらにTypescriptの学習を進めたい方のために、いくつかのリソースを紹介します。
これらのリソースを活用することで、TypeScriptの型システムについてより深い知識を得ることができるでしょう。
おすすめの書籍
ゼロからわかる TypeScript入門
技術評論社から出版されている「ゼロからわかる TypeScript入門」は、プログラミング初心者や本職プログラマーではない方を主な対象にした入門書です。
変数・条件分岐・ループといった基本から、クラスやインターフェース、モジュールまで段階的に学べる構成になっています。最終章ではWeb APIとJSONを使った非同期Webアプリの作成も体験できるので、「実際に動くものを作る」ところまで到達できます。
プロを目指す人のためのTypeScript入門
技術評論社の「プロを目指す人のためのTypeScript入門 安全なコードの書き方から高度な型の使い方まで」、通称 ブルーベリー本 です。
JavaScriptの仕様とTypeScript独自の機能を両方押さえつつ、リテラル型・ユニオン型・keyof型・ジェネリクスなど、高度な型表現まで踏み込んで解説しています。TypeScriptの型システムの表現力を本格的に学べる一冊です。
オンラインで参照できる公式ドキュメント
TypeScript公式ハンドブック
https://www.typescriptlang.org/docs/
TypeScriptの公式ドキュメントです。
intersection型を含む、すべての型システムの機能について詳細な説明があります。
TypeScript Deep Dive
https://basarat.gitbook.io/typescript/
TypeScriptの深い部分まで掘り下げて解説しているオンラインブックです。
無料で読むことができ、intersection型についても詳しく説明されています。
TypeScriptの学習は終わりがありません。
新しい機能が常に追加され、より良い書き方が発見されています。
継続的に学習を続けることで、より良いTypeScriptプログラマーになれるはずです。
まとめ — よく使うユーティリティ型5つの使い分け
この記事で紹介した5つのユーティリティ型を振り返ります。
| ユーティリティ型 | 何をするか | 使いどころ |
|---|---|---|
Partial<T> |
全プロパティを任意に | 更新処理、入力途中のデータ |
Readonly<T> |
全プロパティを変更禁止に | 設定値、変えてはいけない定数 |
Pick<T, K> |
指定したプロパティだけ取り出す | 必要なフィールドだけ使いたいとき |
Omit<T, K> |
指定したプロパティだけ除外する | 一部だけ除きたいとき |
Record<K, T> |
キーと値の型でオブジェクト型を作る | ステータスとメッセージのマッピングなど |
PickとOmitの使い分けは「除きたいプロパティが少なければOmit、取り出したいプロパティが少なければPick」という基準で考えると判断しやすいです。
ユーティリティ型はほかにも Required・Exclude・Extract・NonNullable など多数ありますが、まずはこの5つを使えるようになるのが第一歩です。
as const や satisfies の使い方が気になる方は、こちらの記事も参考にしてみてください。
※本記事の本文案はAIを活用して作成していますが、記載している内容およびコードは筆者が実際に調査、検証・実行し、内容の正確性を確認した上で公開しています。






