🐸

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