APIレスポンスでのジェネリクス活用例
複数のAPIが異なるデータ構造を返す場合でも、共通の型定義で型安全に処理を統一するのがジェネリクスの強みです。
✅ 共通のレスポンス構造を型で定義
type ApiResponse
<T> = {
httpStatus: number;
data: T;
};
T
の部分を、APIごとに異なる「中身の型」として柔軟に差し替え可能success
,data
など共通構造を DRY に保てる
🧩 具体例:API A と API B
🔸 API A: ユーザー情報を返すエンドポイント
// API A の個別データ型
type User = {
id: number;
name: string;
email: string;
};
// API A のレスポンス型(ジェネリクスで生成)
type UserResponse = ApiResponse
<User>;
const resA: UserResponse = {
httpStatus: 200,
data: {
id: 1,
name: "Alice",
email: "[email protected]",
},
};
🔸 API B: 商品一覧を返すエンドポイント
type Product = {
id: string;
title: string;
price: number;
};
// Product[] を返すAPI
type ProductListResponse = ApiResponse<Product[]>;
const resB: ProductListResponse = {
httpStatus: 200,
data: [
{ id: "p1", title: "iPhone", price: 999 },
{ id: "p2", title: "MacBook", price: 1999 },
],
};
💡 もしジェネリクスを使わなかったら…?
// API A 専用の型
type ApiAResponse = {
httpStatus: boolean;
data: {
id: number;
name: string;
email: string;
};
};
// API B 専用の型
type ApiBResponse = {
httpStatus: boolean;
data: {
id: string;
title: string;
price: number;
}[];
};
- 同じ
success
やdata
構造なのに 毎回同じ型を手で書く必要がある - 型変更が発生したときに 重複部分がメンテナンスの負債になる
✅ ジェネリクスを使うメリットまとめ
利点 | 説明 |
---|---|
✅ 共通構造の定義 | `ApiResponse |
で success, data` を一元管理 |
|
✅ 各APIに柔軟対応 | User , Product[] など中身を切り替えて使える |
✅ 型補完・安全性 | res.data.name や res.data[0].price なども補完可能 |
✅ コードの重複排除 | 毎回型を定義し直す必要がない(DRY) |
🎯 さらに応用するなら…
- `PaginatedResponse
` などページネーション付き型にも応用可能 Result<T, E>
のような成功/失敗型にも拡張できる- `useApi
()` のようなカスタムフックの汎化にも利用できる