カテゴリ: TypeScript 更新日: 2025/12/04

TypeScriptでクラスにジェネリクスを適用する方法を徹底解説!初心者でもわかる型の使い回し

TypeScriptでクラスにジェネリクスを適用する方法
TypeScriptでクラスにジェネリクスを適用する方法

先生と生徒の会話形式で理解しよう

生徒

「先生、TypeScriptでクラスを使っているんですが、毎回型を決め打ちするのが不便です。もっと柔軟に使う方法はありますか?」

先生

「良いポイントに気づきましたね。そんなときに役立つのがジェネリクスです。ジェネリクスを使うと、クラスに型を後から指定できるようになります。」

生徒

「なるほど!型を柔軟に扱えるってことですね。でも具体的にどう書くんですか?」

先生

「それでは、TypeScriptでクラスにジェネリクスを適用する方法を、例を交えてわかりやすく説明していきましょう!」

1. ジェネリクスとは?

1. ジェネリクスとは?
1. ジェネリクスとは?

ジェネリクス(Generics)とは、「型を後から決める仕組み」です。通常の変数は値を入れますが、ジェネリクスでは「型の入れ物」を用意して、必要なときに具体的な型を当てはめることができます。

例えば、「箱」というクラスを作るとします。箱の中に「文字列」を入れることもあれば「数値」を入れることもあります。そのたびに新しいクラスを作っていたら大変です。そこでジェネリクスを使えば、箱の中に入れるものの型を自由に切り替えられるようになります。

2. クラスにジェネリクスを適用する基本構文

2. クラスにジェネリクスを適用する基本構文
2. クラスにジェネリクスを適用する基本構文

ジェネリクスを使ったクラスは、クラス名の後ろに山かっこのような記号<>を書き、その中に型のパラメータを入れます。通常はTという記号を使いますが、意味がわかりやすいようにItemTypeなど好きな名前を付けることもできます。


class Box<T> {
    private value: T;

    constructor(value: T) {
        this.value = value;
    }

    getValue(): T {
        return this.value;
    }
}

このクラスは「Box」という名前ですが、中に入れるものの型をTというパラメータで表しています。

3. ジェネリクスを使ったクラスの利用例

3. ジェネリクスを使ったクラスの利用例
3. ジェネリクスを使ったクラスの利用例

次に、このジェネリッククラスを使ってみましょう。使うときに型を指定することで、文字列でも数値でも扱えるようになります。


const stringBox = new Box<string>("こんにちは");
console.log(stringBox.getValue()); // 文字列として扱える

const numberBox = new Box<number>(123);
console.log(numberBox.getValue()); // 数値として扱える

こんにちは
123

このように、同じ「Box」クラスでも、使うときに型を切り替えられるので、とても柔軟です。

4. 複数のジェネリクスを使う

4. 複数のジェネリクスを使う
4. 複数のジェネリクスを使う

ジェネリクスは一つだけでなく、複数の型パラメータを同時に扱うこともできます。例えば「キーと値のペア」を管理するクラスを作りたい場合、以下のように書けます。


class Pair<K, V> {
    private key: K;
    private value: V;

    constructor(key: K, value: V) {
        this.key = key;
        this.value = value;
    }

    getKey(): K {
        return this.key;
    }

    getValue(): V {
        return this.value;
    }
}

const pair = new Pair<string, number>("年齢", 30);
console.log(pair.getKey());   // "年齢"
console.log(pair.getValue()); // 30

年齢
30

この例では、stringnumberを別々に指定しています。つまり一つのクラスで異なる型の組み合わせを表現できるのです。

5. 実際の開発での活用例

5. 実際の開発での活用例
5. 実際の開発での活用例

ジェネリクスは、現実的なプログラミングでとても役に立ちます。例えば、データベースから取得したデータを一時的に格納する「リスト」や「コレクション(集まり)」を扱うときに便利です。

例えば、文字列だけを管理するリスト、数値だけを管理するリストなどをそれぞれ作らなくても、ジェネリクスクラスを使えば、ひとつの仕組みで全て対応できます。


class DataList<T> {
    private items: T[] = [];

    add(item: T): void {
        this.items.push(item);
    }

    getAll(): T[] {
        return this.items;
    }
}

const names = new DataList<string>();
names.add("太郎");
names.add("花子");
console.log(names.getAll());

const scores = new DataList<number>();
scores.add(90);
scores.add(75);
console.log(scores.getAll());

[ '太郎', '花子' ]
[ 90, 75 ]

このように、同じクラスを何度も使い回せるのがジェネリクスの大きな強みです。

6. ポイント整理

6. ポイント整理
6. ポイント整理

TypeScriptのジェネリクスクラスを使うと、ひとつのクラスで複数の型に対応できるようになります。これにより、同じようなクラスを型ごとに作り直す必要がなくなり、効率よく柔軟なプログラムを書けるようになります。特に実務でのデータ管理や再利用性を高めるために欠かせない仕組みです。

まとめ

まとめ
まとめ

TypeScriptでクラスにジェネリクスを適用する考え方を振り返ると、ジェネリクスが「型の再利用性」と「柔軟性」を大幅に高める重要な仕組みであることがはっきり理解できます。特に、同じような構造のクラスを型違いで何度も作成する手間を省き、必要に応じて自由に型を切り替えられるという点は、複雑なデータ管理を行う実務でも強力な武器となります。ひとつのクラスが複数の型に対応し、どのようなデータ構造にも適応できることで、冗長な記述を避けながら整理されたコードを保ちやすくなるのがジェネリクスの最大の魅力です。 また、ジェネリクスは単に型の柔軟性を広げるだけではなく、TypeScriptの型システムと協力して安全なプログラム構造を実現してくれます。ジェネリクスを使わずに型を固定してしまうと、異なる用途に合わせて複数のクラスを用意する必要がありますが、ジェネリクスを導入することで「型が変わっても同じ操作ができる」統一的な仕組みが構築できます。これにより、コード全体の再利用性が高まり、管理もしやすくなります。 とくに複数のジェネリクスを使ったペア構造の管理や、データリストのように「複数の型のデータを扱う可能性があるクラス」を設計する際には、その効果がわかりやすく現れます。実際の開発では、データベースから取得したレコードや、複数タイプの値を扱うフォームデータなど、多種多様な場面でジェネリクスが活用されます。さらに、ジェネリクスを用いるとクラスの使い回しが可能となり、さまざまなデータ型を扱う必要がある環境でも柔軟に対応できるため、長期的なプロジェクトにおいても保守のしやすさを大きく向上させます。 以下に、今回学んだ内容を整理しながら、ジェネリクスの魅力を再確認できるサンプルプログラムを用意しました。実際の開発でもよく使われるパターンなので、使い方を理解しながら読み進めてみるとさらに理解が深まります。

サンプルプログラム:ジェネリクスを活用した格納クラス


class StorageBox<T> {
    private item: T;
    private static createdCount: number = 0;

    constructor(item: T) {
        this.item = item;
        StorageBox.createdCount++;
    }

    getItem(): T {
        return this.item;
    }

    static getCount(): number {
        return StorageBox.createdCount;
    }
}

const box1 = new StorageBox<string>("りんご");
const box2 = new StorageBox<number>(300);
const box3 = new StorageBox<boolean>(true);

console.log(box1.getItem()); 
console.log(box2.getItem()); 
console.log(box3.getItem()); 
console.log(StorageBox.getCount());

このサンプルプログラムでは、ジェネリクスを使うことで、クラスがどんな型のデータでも柔軟に格納できるようになっています。さらに、staticプロパティを組み合わせることで、何個のインスタンスが生成されたかを共通で管理する仕組みも追加しています。ジェネリクスによる型の使い回しと、staticを使ったクラス単位の管理が組み合わさることで、より高い拡張性と実用性を持つクラス設計が実現できることが確認できます。 こうした仕組みは、データ管理、ログ管理、設定情報の保持など、現実的なシステムのさまざまな場面で応用でき、TypeScriptの強みを最大限に活かした設計につながります。

先生と生徒の振り返り会話

生徒

「ジェネリクスってこんなに便利なんですね。同じクラスを何度も作らなくていいのは助かります!」

先生

「その通りです。型を後から自由に指定できるので、ひとつのクラスでいろいろな用途に対応できますよ。」

生徒

「複数のジェネリクスを扱う方法もわかりました!ペアの例はとてもイメージしやすかったです。」

先生

「良いですね。実務ではデータ構造の管理にジェネリクスが活躍する場面が多いので、今の理解は必ず役に立ちます。」

生徒

「はい!これからクラスを書くときは、まずジェネリクスを使える場面がないか意識してみます!」

関連記事:
カテゴリの一覧へ
新着記事
New1
TypeScript
TypeScriptでパスエイリアスを設定する方法!baseUrlとpathsでコードをスッキリ整理
New2
JavaScript
JavaScriptのfor文の書き方を初心者向けにやさしく解説
New3
JavaScript
JavaScriptの関数でよくあるエラーとその解決法まとめ
New4
JavaScript
JavaScriptのイベント処理でよくあるエラーとその対処法
人気記事
No.1
Java&Spring記事人気No1
JavaScript
JavaScriptのインストール方法まとめ!Windows・Mac・Linux別にステップ解説
No.2
Java&Spring記事人気No2
JavaScript
JavaScriptのマウスイベントの使い方(click, mouseoverなど)
No.3
Java&Spring記事人気No3
JavaScript
JavaScriptのtoStringとString関数の違いを初心者向けに解説
No.4
Java&Spring記事人気No4
JavaScript
JavaScriptの純粋関数(pure function)と副作用の違いを理解しよう
No.5
Java&Spring記事人気No5
JavaScript
JavaScriptプログラムの実行方法まとめ!ブラウザ・Node.js・コンソールの使い方
No.6
Java&Spring記事人気No6
TypeScript
TypeScript学習におすすめの無料教材・リファレンスサイト【初心者向け】
No.7
Java&Spring記事人気No7
JavaScript
JavaScriptで文字列をforループで1文字ずつ処理する方法!初心者向け解説
No.8
Java&Spring記事人気No8
JavaScript
JavaScriptのDOMContentLoadedとloadイベントの違いを理解しよう