4
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

TypeScriptのUtility Typesをある程度理解してコード読解力を上げたい

4
Last updated at Posted at 2026-01-27

はじめに

先輩の書いたコードやライブラリのソースコードを覗いたりするとPartial<T>Pick<T, K>といった見慣れない型表記に出会い、それらの理解に時間をかけてしまうことがよくあります

これらは Utility Types(ユーティリティ型) と呼ばれ、TypeScriptが標準で提供している型変換のためのツールです。

Utility Typesを理解すると、以下のメリットがあります。

  • ライブラリやフレームワークのソースコードが読めるようになる
  • 型安全性を保ちながら柔軟なコードが書ける

この記事では、特によく使われるUtility Types紹介します。

1. Partial<T> - すべてのプロパティをオプショナルに

Partial<T>は、型Tのすべてのプロパティをオプショナル(?付き)に変換します。

interface User {
  id: number;
  name: string;
  email: string;
}

type PartialUser = Partial<User>;
// 結果:
// {
//   id?: number;
//   name?: string;
//   email?: string;
// }

更新APIで一部のフィールドだけを変更したい場合や、設定オブジェクトでデフォルト値を持つ項目を表現する際によく使われます。

2. Required<T> - すべてのプロパティを必須に

Required<T>Partial<T>の逆で、すべてのプロパティから?を取り除いて必須にします。

interface Config {
  apiUrl?: string;
  timeout?: number;
  retryCount?: number;
}

type RequiredConfig = Required<Config>;
// 結果:
// {
//   apiUrl: string;
//   timeout: number;
//   retryCount: number;
// }

オプショナルな設定オブジェクトにデフォルト値を適用した後の型として使ったり、「この時点では全フィールドが確定している」ことを型で表現する際に活用できます。

3. Readonly<T> - すべてのプロパティを読み取り専用に

Readonly<T>は、すべてのプロパティにreadonly修飾子を付与します。

interface Todo {
  title: string;
  completed: boolean;
}

type ReadonlyTodo = Readonly<Todo>;
// 結果:
// {
//   readonly title: string;
//   readonly completed: boolean;
// }

const todo: ReadonlyTodo = { title: "Learn TypeScript", completed: false };
// todo.completed = true; // Error: Cannot assign to 'completed'

状態管理で変更不可なデータを扱う場合や、関数の引数を変更されたくない場合に使用します。

4. Pick<T, K> - 特定のプロパティだけを抽出

Pick<T, K>は、型Tから指定したキーKのプロパティだけを抽出した新しい型を作ります。

interface User {
  id: number;
  name: string;
  email: string;
  password: string;
  createdAt: Date;
}

type PublicUser = Pick<User, "id" | "name" | "email">;
// 結果:
// {
//   id: number;
//   name: string;
//   email: string;
// }

APIレスポンスで公開可能な情報だけを返す型を定義したり、一覧表示用に軽量な型を作る際に便利です。

5. Omit<T, K> - 特定のプロパティを除外

Omit<T, K>Pickの逆で、指定したキーを除外した型を作ります。

interface Article {
  id: number;
  title: string;
  content: string;
  createdAt: Date;
  updatedAt: Date;
}

type CreateArticleInput = Omit<Article, "id" | "createdAt" | "updatedAt">;
// 結果:
// {
//   title: string;
//   content: string;
// }

新規作成リクエストで自動生成されるフィールド(id、タイムスタンプなど)を除外した型を作る場合によく使われます。

6. Record<K, T> - オブジェクト型を簡潔に定義

Record<K, T>は、キーの型がK、値の型がTであるオブジェクト型を作ります。

type Status = "pending" | "approved" | "rejected";

interface StatusConfig {
  label: string;
  color: string;
}

const statusConfigs: Record<Status, StatusConfig> = {
  pending: { label: "審査中", color: "yellow" },
  approved: { label: "承認済", color: "green" },
  rejected: { label: "却下", color: "red" },
};

ステータスや言語コードなどのUnion型をキーにしたマッピングオブジェクトを定義する際に活用します。キーの追加漏れをコンパイル時に検出できるのが利点です。

7. Exclude<T, U> - Union型から除外

Exclude<T, U>は、Union型TからUに代入可能な型を除外します。

type AllColors = "red" | "green" | "blue" | "yellow";
type WarmColors = "red" | "yellow";

type CoolColors = Exclude<AllColors, WarmColors>;
// 結果: "green" | "blue"

HTTPメソッドから特定のメソッドを除外したり、イベントタイプの一部だけを許可する型を作る場合などに使えます。

8. Extract<T, U> - Union型から抽出

Extract<T, U>Excludeの逆で、Union型TからUに代入可能な型だけを抽出します。

type AllTypes = string | number | boolean | null | undefined;

type Primitives = Extract<AllTypes, string | number | boolean>;
// 結果: string | number | boolean

複数のイベント型から特定カテゴリのイベントだけを抽出したり、許可する値を明示的に制限する際に役立ちます。

9. NonNullable<T> - null/undefinedを除外

NonNullable<T>は、型からnullundefinedを除外します。

type MaybeString = string | null | undefined;

type DefiniteString = NonNullable<MaybeString>;
// 結果: string

nullチェック後の型を明示したい場合や、配列からnullをフィルタリングした後の型を表現する際に使います。

10. ReturnType<T> - 関数の戻り値の型を取得

ReturnType<T>は、関数型Tの戻り値の型を取得します。

function createUser(name: string, age: number) {
  return {
    id: Math.random(),
    name,
    age,
    createdAt: new Date(),
  };
}

type User = ReturnType<typeof createUser>;
// 結果:
// {
//   id: number;
//   name: string;
//   age: number;
//   createdAt: Date;
// }

ライブラリの関数から戻り値の型を取得して再利用したり、型定義が提供されていない関数の型を推論する際に便利です。

11. Parameters<T> - 関数の引数の型を取得

Parameters<T>は、関数型Tの引数の型をタプルとして取得します。

function greet(name: string, age: number, isAdmin: boolean): string {
  return `Hello, ${name}!`;
}

type GreetParams = Parameters<typeof greet>;
// 結果: [name: string, age: number, isAdmin: boolean]

type FirstParam = Parameters<typeof greet>[0]; // string

既存の関数と同じシグネチャを持つラッパー関数を作る場合や、関数の特定の引数の型だけを取り出したい場合に活用できます。

12. Awaited<T> - Promiseをアンラップ

Awaited<T>は、Promise<T>からTを取り出します。ネストしたPromiseも再帰的にアンラップします。

type A = Awaited<Promise<string>>;
// 結果: string

type B = Awaited<Promise<Promise<number>>>;
// 結果: number(ネストも解消)

ReturnTypeと組み合わせて非同期関数の実際の戻り値の型を取得する際によく使われます(Awaited<ReturnType<typeof asyncFunc>>)。

実践:複数のUtility Typesを組み合わせる

複数のUtility Typesを組み合わせて使うことが多いです。

interface User {
  id: number;
  name: string;
  email: string;
  role: "admin" | "user";
  createdAt: Date;
  updatedAt: Date;
}

// 編集フォームの型:id等を除外し、残りをオプショナルに
type UserEditForm = Partial<Omit<User, "id" | "createdAt" | "updatedAt">>;

// 内部設定の型:すべて必須かつ読み取り専用
type InternalConfig = Readonly<Required<Config>>;

まとめ

Utility Type 役割 よくある使い方
Partial<T> 全プロパティをオプショナルに 更新処理、部分的な設定
Required<T> 全プロパティを必須に デフォルト値適用後
Readonly<T> 全プロパティを読み取り専用に 変更不可な状態
Pick<T, K> 特定のプロパティを抽出 APIレスポンスの型定義
Omit<T, K> 特定のプロパティを除外 作成リクエストの型定義
Record<K, T> キーと値の型を指定 マッピングオブジェクト
Exclude<T, U> Union型から除外 特定の値を除外
Extract<T, U> Union型から抽出 特定の値だけ許可
NonNullable<T> null/undefinedを除外 値が確実に存在する場合
ReturnType<T> 関数の戻り値の型を取得 ライブラリの型再利用
Parameters<T> 関数の引数の型を取得 ラッパー関数
Awaited<T> Promiseをアンラップ 非同期関数の戻り値

Utility Typesを使いこなすことで、型定義の重複を減らし、変更に強い型設計ができるようになります
書けなくても、読めることができればコードを紐解く時間を大幅に削減することができます!

余談

mosyaのType Challengesで型パズルに挑戦することができます
難易度高めなので是非挑戦してみてください

4
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
4
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?