完全な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;
}
型の構造化
- リーフから始める — 最も内側の型を最初に定義します(
Profile、次にUser)。 - 再利用可能な型を抽出する —
Paginationは多くのリストエンドポイントに出現するため、一度だけ定義します。 - statusフィールドを絞り込む —
status: stringをstatus: "success" | "error"に変更して型安全性を向上させます。 - エラー形状を追加する — APIレスポンスは成功とエラーで異なる形状を持つことが多いです。判別ユニオンを使って両方を処理します。
ジェネリック化
異なるリソースのページネーション付きリストを返すAPIの場合、ジェネリックラッパーを作成します:
interface PaginatedResponse<T> {
status: "success";
data: {
items: T[];
pagination: Pagination;
};
requestId: string;
}
// 使用例
type UserListResponse = PaginatedResponse<User>;
これにより、すべてのエンドポイントでエンベロープ構造の重複を避けられます。
ユースケース
REST APIのフロントエンドクライアントライブラリを構築し、fetchラッパーでエンドツーエンドの型安全性を実現するために、すべてのレスポンス形状の完全なTypeScriptカバレッジが必要な場合に使用します。