完全なAPIレスポンスJSONをTypeScriptで型定義する

メタデータ、ページネーション、ネストされたデータを含む完全なREST APIレスポンスをTypeScript interfaceセットに変換する方法を学びます。

Advanced Patterns

詳細な説明

実際のAPIレスポンスの型定義

本番環境のAPIレスポンスはデータペイロードだけではありません。メタデータ、ページネーション情報、エラーフィールド、深くネストされたオブジェクトを含みます。レスポンス全体をTypeScriptの型に変換するには体系的なアプローチが必要です。

JSON例

{
  "status": "success",
  "data": {
    "users": [
      {
        "id": 1,
        "name": "Alice",
        "email": "alice@example.com",
        "profile": {
          "avatar": "https://cdn.example.com/alice.jpg",
          "bio": "Full-stack developer"
        }
      }
    ],
    "pagination": {
      "page": 1,
      "perPage": 20,
      "total": 150,
      "totalPages": 8
    }
  },
  "requestId": "req_abc123"
}

生成されるTypeScript

interface Profile {
  avatar: string;
  bio: string;
}

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

interface Pagination {
  page: number;
  perPage: number;
  total: number;
  totalPages: number;
}

interface ApiResponse {
  status: string;
  data: {
    users: User[];
    pagination: Pagination;
  };
  requestId: string;
}

型の構造化

  1. リーフから始める — 最も内側の型を最初に定義します(Profile、次にUser)。
  2. 再利用可能な型を抽出するPaginationは多くのリストエンドポイントに出現するため、一度だけ定義します。
  3. statusフィールドを絞り込むstatus: stringstatus: "success" | "error"に変更して型安全性を向上させます。
  4. エラー形状を追加する — APIレスポンスは成功とエラーで異なる形状を持つことが多いです。判別ユニオンを使って両方を処理します。

ジェネリック化

異なるリソースのページネーション付きリストを返すAPIの場合、ジェネリックラッパーを作成します:

interface PaginatedResponse<T> {
  status: "success";
  data: {
    items: T[];
    pagination: Pagination;
  };
  requestId: string;
}

// 使用例
type UserListResponse = PaginatedResponse<User>;

これにより、すべてのエンドポイントでエンベロープ構造の重複を避けられます。

ユースケース

REST APIのフロントエンドクライアントライブラリを構築し、fetchラッパーでエンドツーエンドの型安全性を実現するために、すべてのレスポンス形状の完全なTypeScriptカバレッジが必要な場合に使用します。

試してみる — JSON to TypeScript

フルツールを開く