🐸
TypeScript ジェネリクス
はじめに:ジェネリクスとは?
TypeScriptの「ジェネリクス(Generics)」とは、
型をパラメーターのように扱える機能です。
関数・クラス・インターフェースなどで型を固定せず、
柔軟に使い回せるようになるため、再利用性と型安全性の両立が実現できます。
基本的な使い方
const foo = <T>(bar: T): T => {
return bar
}
const result1 = foo<string>("hello"); // 型を明示的に指定 → T = string
const result2 = foo(123); // 型推論 → T = number
ここでの <T> は「型の変数」のようなもので、
引数 bar の型と、戻り値の型を一致させつつ柔軟に対応できるようにしています。
ジェネリクスを使うメリット
型安全性が高い
const wrapInArray = <T>(value: T): T[] => {
return [value];
}
const wrapped = wrapInArray("text");
// wrapped の型は string[] に自動推論される
T に応じて戻り値の配列型が変化するため、安全な型付けが保証されます。
型の再利用性が高い
同じロジックで異なる型に対応可能。
インターフェース × ジェネリクス
interface ApiResponse<T> {
data: T;
status: number;
}
const userResponse: ApiResponse<{ name: string }> = {
data: { name: "Alice" },// ← data の型は { name: string }
status: 200
};
このように、dataの型が渡した型パラメータ { name: string } になります。
ジェネリクスに制約をつける(extends)
const getLength = <T extends { length: number }>(arg: T): number => {
return arg.length;
}
getLength("hello"); // OK lengthは5
getLength([1, 2, 3]); // OK lengthは3
getLength(42); // エラー: numberにはlengthがない
これは、ジェネリック型 T に対して「length プロパティを持っている型だけを許可する」という
制約を課しています。
- T は必ず length というプロパティを持っていなければならない。
- length の型は number である必要がある。
まとめ
- ジェネリクスは「型の変数」のようなもの。
- 同じ関数やクラスでも、異なる型で柔軟に使える(再利用性が高い)。
- 型を明示的に指定することも、TypeScriptに推論させることもできる。
-
extends
を使って、特定の条件を満たす型だけを許可することも可能。
Discussion