TL

ジェネリクス(総称型)

型を“引数”のように後から指定できる仕組み。同じコードを複数の型で安全に再利用でき、型安全とコード共通化を両立できます。

中級ジェネリクス型システム型安全最終更新: 2026-06-06
TL;DR要点だけ先に
  • 1.ジェネリクスは型をパラメータ化し、1つの定義を多くの型で使い回す仕組みです。
  • 2.`List<T>` のように型引数を渡すと、各要素の型が保たれ型安全とコード共通化を両立できます。
  • 3.型ごとにコードを複製する必要がなく、何でも型(Object など)に頼るより安全です。

ジェネリクスとは

ジェネリクス(総称型)は、関数やクラスを特定の型に縛らず書き、使うときに型を「引数」のように渡せる仕組みです。値を受け取る引数があるように、型を受け取る引数があると考えると分かりやすいです。

  • 「整数のリスト」「文字列のリスト」を別々に作らず、1つの List 定義で済ませられます。
  • 取り出した要素の型が保たれるため、コンパイラが誤った使い方を弾けます。
  • 型引数は慣例で T(Type)や E(Element)などの記号で書きます。

つまり「同じロジックを、いろいろな型で安全に再利用する」ための道具です。

なぜ必要か:3つの選択肢

ジェネリクスが無い世界では、複数の型に対応する方法が限られ、どれも欠点があります。

方法内容問題点
型ごとに複製IntListStringList を別々に書くコード重複。修正漏れの温床
何でも型を使う中身を Object / any で持つ取り出し時に型が消え、安全でない
ジェネリクス型を引数化し1つで共通化型安全と再利用を両立

「何でも型」は一見柔軟ですが、取り出すたびにキャスト(型変換)が必要で、間違えても実行時まで気づけません。ジェネリクスはこの欠点を解消します。

基本的な書き方

List<T>T が型引数です。List<int> と書けば「int のリスト」として振る舞い、add には int しか入れられず、取り出した値も int として扱えます。

// TypeScript:型引数 T を取る関数
function first<T>(items: T[]): T {
  return items[0];
}

const n = first<number>([1, 2, 3]); // n の型は number
const s = first(["a", "b"]);        // 推論で T = string
// Java:型引数を持つクラスの利用
List<String> names = new ArrayList<>();
names.add("Alice");
String head = names.get(0); // キャスト不要・String と分かっている

多くの言語では、渡した値から型引数を自動推論してくれるため、毎回 <...> を明示する必要はありません。

制約(境界)を付ける

「どんな型でもよい」ではなく「ある条件を満たす型に限る」としたい場面があります。これを**型制約(境界)**と呼びます。たとえば「比較できる型だけ」「特定のインターフェースを実装した型だけ」と縛れます。

interface HasLength {
  length: number;
}
// length を持つ型に限定する
function longest<T extends HasLength>(a: T, b: T): T {
  return a.length >= b.length ? a : b;
}
longest("ab", "abc"); // 文字列も配列も length を持つので OK

制約を付けると、その型が持つメンバ(上記なら length)を安全に使えます。制約なしの型引数は「何が来るか不明」なので、限定された操作しかできません。

まずは推論に任せる

型引数は明示しなくても、引数の値から推論されることが多いです。first([1, 2, 3]) のように書けば T は自動で決まります。読みづらいときや推論が効かないときだけ <number> を明示しましょう。

注意点

便利な一方で、言語ごとの実装の違いに起因する落とし穴があります。

言語による実行時の扱いの差

Java は 型消去(type erasure) を採用し、実行時には型引数の情報が消えます。そのため実行時に「T が何か」を直接調べる処理は書けません。一方 C# は実行時にも型情報を保持します。ジェネリクスは万能の動的機構ではなく、主にコンパイル時の安全装置だと捉えると誤解を避けられます。

過度に多くの型引数を持たせると、シグネチャが読みにくくなります。必要な範囲にとどめるのがコツです。

まとめ

ジェネリクスは型を引数化して、同じコードを多くの型で安全に再利用する仕組みです。List<T> のように型を渡すことで、要素の型が保たれ、型安全とコード共通化を両立できます。型ごとの複製や「何でも型」に頼らず、必要なら制約で対象を絞る。これがジェネリクスを使いこなす基本です。

プログラミング Article

ジェネリクス(総称型)を実務で読む

TL;DRは入口です。実際に選ぶ・使う段階では、何を解決するか、何と比較するか、導入後にどこで詰まるかまで見る必要があります。

解決すること

ジェネリクス

比較で見る軸

難易度: intermediate / カテゴリ: プログラミング / タグ数: 3

導入後に効く点

`List<T>` のように型引数を渡すと、各要素の型が保たれ型安全とコード共通化を両立できます。

先に潰すリスク

用語だけ覚えても、設計・実装・運用でどこに効くかを確認しないと判断を誤る。

数字・仕様の読み方
難易度
intermediate
カテゴリ
プログラミング
タグ数
3

判断チェックリスト

  • 自社の用途が「ジェネリクス / 型システム」に近いか確認する。
  • 強みである「ジェネリクスは型をパラメータ化し、1つの定義を多くの型で使い回す仕組みです。」が本当に評価軸になるか確認する。
  • 注意点の「用語だけ覚えても、設計・実装・運用でどこに効くかを確認しないと判断を誤る。」を運用で吸収できるか確認する。
  • 公開値や仕様値は、対象プラン・対象機種・対象リージョンまで確認する。
  • 既存システム、ID、ネットワーク、監視、バックアップとの接続方法を先に洗い出す。
  • 小さく試してから、本番移行、権限設計、障害時手順、コスト監視を決める。

次に確認する観点

ジェネリクス型システム型安全ジェネリクス型システム型安全
参考: 公式情報