ジェネリクス
型をパラメータ化し、型安全性を保ちながら汎用的なコードを書く仕組み
TypeScript型システム
ジェネリクスとは
ジェネリクス (Generics) は、型をパラメータ化し、型安全性を保ちながら汎用的なコードを書く仕組みである。any を使わずに、様々な型で動作する関数やクラスを定義できる。
基本
// ❌ any: 型安全性がない
function first(arr: any[]): any { return arr[0]; }
// ✅ ジェネリクス: 型安全
function first<T>(arr: T[]): T | undefined { return arr[0]; }
first([1, 2, 3]); // number
first(['a', 'b', 'c']); // string
制約 (extends)
// T は length プロパティを持つ型に制限
function longest<T extends { length: number }>(a: T, b: T): T {
return a.length >= b.length ? a : b;
}
longest('hello', 'world'); // ✅ string は length を持つ
longest([1, 2], [1, 2, 3]); // ✅ 配列は length を持つ
longest(1, 2); // ❌ number は length を持たない
複数の型パラメータ
function map<T, U>(arr: T[], fn: (item: T) => U): U[] {
return arr.map(fn);
}
map([1, 2, 3], n => n.toString()); // string[]
ジェネリクスの実用例
API レスポンスの型
interface ApiResponse<T> {
data: T;
status: number;
message: string;
}
async function fetchApi<T>(url: string): Promise<ApiResponse<T>> {
const res = await fetch(url);
return res.json();
}
const { data } = await fetchApi<User[]>('/api/users');
// data の型: User[]
DynamoDB のリポジトリ
interface Repository<T> {
findById(id: string): Promise<T | null>;
save(item: T): Promise<void>;
}
class DynamoDBRepository<T> implements Repository<T> {
constructor(private tableName: string) {}
async findById(id: string) { /* ... */ }
async save(item: T) { /* ... */ }
}
const userRepo = new DynamoDBRepository<User>('users');
const orderRepo = new DynamoDBRepository<Order>('orders');
ユーティリティ型
| 型 | 説明 |
|---|---|
Partial<T> |
全プロパティをオプショナルに |
Required<T> |
全プロパティを必須に |
Pick<T, K> |
指定プロパティだけ抽出 |
Omit<T, K> |
指定プロパティを除外 |
Record<K, V> |
キーと値の型を指定したオブジェクト |
type UserUpdate = Partial<Pick<User, 'name' | 'email'>>;
// { name?: string; email?: string }
ジェネリクスの理解を深めるには関連書籍が参考になる。