関数の引数でジェネリクスを活用する例
関数の引数にジェネリクスを使うことで、「どんな型の値が来ても型安全に処理できる」「補完が効く」「再利用性が高い」など多くの利点があります。
✅ 目的:あらゆる型に対応できる関数を型安全に定義する
function echo
<T>(value: T): T {
return value;
}
✅ 使用例
echo("hello"); // string → string
echo(123); // number → number
echo({ id: 1 }); // { id: number } → { id: number }
value: T
に与えた型がそのまま戻り値に反映される- 型キャスト不要、any不使用でも型安全
📌 固定型との比較
function echoString(value: string): string {
return value;
}
echoString("hi"); // OK
echoString(42); // ❌ エラー
- 固定型では 型が1つに縛られてしまい、使い回しできない
🧩 実践例:配列の先頭を取得する関数
❌ anyを使ったバージョン(型安全でない)
function getFirst(arr: any[]): any {
return arr[0];
}
const result = getFirst(["a", "b", "c"]); // result: any
result.toUpperCase(); // ❌ コンパイル通るが実行時エラーの恐れ
✅ ジェネリクスで型安全に
function getFirst
<T>(arr: T[]): T | undefined {
return arr[0];
}
const s = getFirst(["a", "b", "c"]); // string
const n = getFirst([1, 2, 3]); // number
- 戻り値の型が引数の中身に連動
- IDE補完も正しく効く
undefined
も正しく型として表現できる
🎯 キー制限付き引数に使う
function getProp<T, K extends keyof T>(obj: T, key: K): T[K] {
return obj[key];
}
const user = { id: 1, name: "Tom" };
getProp(user, "name"); // OK → string
getProp(user, "id"); // OK → number
// getProp(user, "email"); // ❌ エラー: email は存在しないキー
- 引数に存在するキーしか渡せない
- 戻り値の型が動的に変わる(型安全!)
✅ 関数引数でのジェネリクスの嬉しいポイントまとめ
ポイント | 内容 |
---|---|
✅ 型安全 | any を使わず、渡された型に応じた処理ができる |
✅ 再利用性 | 一度定義すれば複数の型に使い回せる |
✅ 補完が効く | IDEで引数や戻り値に対して正確な補完が出る |
✅ 制約を加えられる | extends によって構造的な制限を加えられる |
📚 まとめ:関数 × ジェネリクスが向いている場面
- データ型が呼び出し元によって変わる(配列・オブジェクトなど)
- 共通の処理ロジックに複数の型を適用したい
- IDE補完や型推論を最大限に活かしたい
keyof
やT[K]
を使った安全な動的アクセスをしたい
function filterByProp<T, K extends keyof T>(
list: T[],
key: K,
value: T[K]
): T[] {
return list.filter(item => item[key] === value);
}
このように、関数の引数でジェネリクスを使うことで、「安全で柔軟」なコードが書けるようになります。