ジェネリクス: 型を抽象化
型安全で再利用可能なコード。any を使わない。
ジェネリクス
型をパラメータ化。
制約
extends で型を限定。
型推論
コンパイラが自動で型を決定。
ジェネリクス基礎
型をハードコードするのではなく、変数(型パラメータ `T`)として扱います。これにより、一つの関数やクラスを様々な型で再利用でき、かつ `any` を使うのと違って「何の型が入っているか」を厳密に追跡できます。
// ジェネリック関数function identity<T>(value: T): T { return value;}
identity<string>("hello"); // 明示的identity(42); // 推論される
// ジェネリック配列関数function first<T>(arr: T[]): T | undefined { return arr[0];}
// 複数の型パラメータfunction pair<K, V>(key: K, value: V): [K, V] { return [key, value];}Bad
// ❌ Bad: any で型安全性を失うfunction identity(value: any): any { return value;}Good
// ✅ Good: ジェネリックで型保持function identity<T>(value: T): T { return value;}パターン
// インターフェースのジェネリックinterface Box<T> { value: T;}const numBox: Box<number> = { value: 42 };
// クラスのジェネリックclass Queue<T> { private items: T[] = []; enqueue(item: T) { this.items.push(item); } dequeue(): T | undefined { return this.items.shift(); }}
// 制約付きジェネリックfunction getLength<T extends { length: number }>(item: T): number { return item.length;}getLength("hello"); // OKgetLength([1, 2, 3]); // OK// getLength(42); // Error!
// デフォルト型type Container<T = string> = { value: T }; Tip: 迷ったら any ではなく unknown。さらに良いのはジェネリクス。
合格ライン
ジェネリック関数を書ける
制約付きジェネリクスを使える
演習課題
課題1: ジェネリック関数
ジェネリック関数を作成してください。
課題2: 制約付きジェネリクス
extends で制約付きジェネリクスを実装してください。