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

TypeScriptのジェネリクスとユニオン型・交差型の組み合わせ活用法

TypeScriptのジェネリクスとユニオン型・交差型の組み合わせ活用法
TypeScriptのジェネリクスとユニオン型・交差型の組み合わせ活用法

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

生徒

「先生、TypeScriptのジェネリクスって便利そうですが、ユニオン型や交差型と一緒に使えるんですか?」

先生

「もちろん使えますよ。ジェネリクス(Generics)とユニオン型・交差型を組み合わせることで、より柔軟で安全なコードを書くことができます。」

生徒

「なるほど!でも、ちょっと難しそうですね…。どんな場面で使うのか、具体的に知りたいです!」

先生

「それでは、ジェネリクスとユニオン型・交差型の基本から、組み合わせた使い方まで、わかりやすく説明していきましょう!」

1. ジェネリクスとは?

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

まず、ジェネリクス(Generics)とは、型をあとから指定できる仕組みのことです。TypeScriptでは、関数やクラス、インターフェースなどに柔軟な型を持たせたいときに使います。たとえば「どんな型でも受け取れる関数」を作りたい場合に便利です。

次の例を見てみましょう。


function identity<T>(value: T): T {
    return value;
}

console.log(identity("文字列"));
console.log(identity(123));

文字列
123

この<T>という部分がジェネリクスです。ここでのTは「型の変数」のようなもので、実際に使うときに「文字列型」や「数値型」などが代入されます。

2. ユニオン型とは?

2. ユニオン型とは?
2. ユニオン型とは?

ユニオン型(Union Type)とは、「複数の型のどれかである」という意味です。つまり、「文字列でも数値でもOK」といった柔軟な型を作ることができます。

例えば次のように書けます。


let value: string | number;

value = "こんにちは";
value = 100;

このように「|」でつなげることで、複数の型を許容できるようになります。

3. 交差型とは?

3. 交差型とは?
3. 交差型とは?

交差型(Intersection Type)は、「複数の型をすべて持つ」という意味です。つまり「Aの型の性質もBの型の性質も持つオブジェクト」を表します。

たとえば次のように使います。


type Person = { name: string };
type Contact = { email: string };

type PersonWithContact = Person & Contact;

const user: PersonWithContact = {
    name: "田中",
    email: "tanaka@example.com"
};

交差型は「&」を使って複数の型を組み合わせるのが特徴です。

4. ジェネリクス × ユニオン型の活用

4. ジェネリクス × ユニオン型の活用
4. ジェネリクス × ユニオン型の活用

ここからが本題です。ジェネリクスとユニオン型を組み合わせることで、「複数の型のどれかを受け取る汎用的な関数」を作ることができます。


function printValue<T extends string | number>(value: T): void {
    console.log(value);
}

printValue("テキスト");
printValue(42);

テキスト
42

このようにT extends string | numberと書くことで、「Tはstringまたはnumberのどちらか」という制約を付けています。これにより、他の型(例えばbooleanなど)は受け付けないようにできます。

この組み合わせは、APIの引数チェックフォーム入力の型安全性を保つ場面などで非常に便利です。

5. ジェネリクス × 交差型の活用

5. ジェネリクス × 交差型の活用
5. ジェネリクス × 交差型の活用

次に、ジェネリクスと交差型の組み合わせを見てみましょう。これは「異なる型の情報をまとめて扱いたい」ときに使います。


function mergeObjects<T, U>(obj1: T, obj2: U): T & U {
    return { ...obj1, ...obj2 };
}

const person = { name: "山田" };
const contact = { email: "yamada@example.com" };

const merged = mergeObjects(person, contact);
console.log(merged.name);
console.log(merged.email);

山田
yamada@example.com

この関数は、2つのオブジェクトを受け取り、それらを結合して新しいオブジェクトを返します。戻り値の型がT & U(交差型)になっているので、両方の型のプロパティが使えるようになります。

つまり、ジェネリクスが「型を柔軟に受け取る」役割を果たし、交差型が「型を合体させる」役割を果たしているのです。

6. 応用例:ユニオン型と交差型を組み合わせた型制御

6. 応用例:ユニオン型と交差型を組み合わせた型制御
6. 応用例:ユニオン型と交差型を組み合わせた型制御

さらに応用すると、ユニオン型と交差型を組み合わせて、より高度な型制御を行うこともできます。たとえば、「特定のキーを持っているかどうか」で動作を変えるような関数です。


type User = { id: number; name: string };
type Admin = { id: number; name: string; role: "admin" };

function getUserInfo<T extends User | Admin>(user: T): string {
    if ("role" in user) {
        return `管理者: ${user.name}`;
    }
    return `ユーザー: ${user.name}`;
}

console.log(getUserInfo({ id: 1, name: "太郎" }));
console.log(getUserInfo({ id: 2, name: "花子", role: "admin" }));

ユーザー: 太郎
管理者: 花子

このようにジェネリクスとユニオン型・交差型を使うことで、柔軟かつ安全に異なるデータ構造を扱えるようになります。

TypeScriptの型システムを理解すると、プログラムのエラーを事前に防ぐことができ、安心して開発を進められるようになります。

まとめ

まとめ
まとめ

ジェネリクスとユニオン型・交差型を組み合わせる意味

ここまで、TypeScriptにおけるジェネリクス、ユニオン型、交差型の基本的な考え方と、それらを組み合わせて使う方法について解説してきました。ジェネリクスは「型をあとから決められる仕組み」であり、ユニオン型は「複数の型のどれかを許容する型」、交差型は「複数の型をすべて満たす型」を表します。これらはそれぞれ単体でも便利ですが、組み合わせることでTypeScriptの型表現は一気に実践的になります。

特に実務の開発現場では、「入力値が複数パターンある」「返却データの構造が条件によって変わる」「共通のプロパティを持ちながら役割が異なるオブジェクトを扱う」といった場面が頻繁に登場します。そのようなケースで、ジェネリクスとユニオン型・交差型を適切に組み合わせることで、コードの柔軟性を保ちながら、型安全性を高いレベルで維持することができます。

ジェネリクス × ユニオン型で実現できること

ジェネリクスとユニオン型を組み合わせる最大のメリットは、「扱える型の範囲を制限しつつ、汎用的な処理を書くことができる」点にあります。たとえば、文字列または数値のみを受け付ける関数を作りたい場合、ジェネリクスにユニオン型の制約を付けることで、想定外の型が入り込むのを防げます。

これにより、APIの引数チェックやユーザー入力の検証、表示用データのフォーマット処理など、さまざまな場面で安全な関数設計が可能になります。any型に頼らず、型の意図を明確に表現できる点は、長期的に見て非常に大きなメリットです。

ジェネリクス × 交差型で設計が整理される理由

一方、ジェネリクスと交差型の組み合わせは、「複数の型情報をまとめて扱いたい」場面で力を発揮します。複数のオブジェクトを結合したり、共通のプロパティを持つデータ構造を一つにまとめたりする場合、交差型を使うことで「すべての性質を持つ型」を自然に表現できます。

ジェネリクスを使うことで、結合する対象の型を柔軟に受け取りつつ、戻り値としては両方の型を満たす安全な型を返すことができます。この考え方は、設定オブジェクトの合成や、ユーザー情報と権限情報の統合など、実務でもよく使われる設計パターンです。

総合的な活用サンプル


type BaseResponse = {
    success: boolean;
};

type DataResponse<T> = BaseResponse & {
    data: T;
};

type ErrorResponse = BaseResponse & {
    errorMessage: string;
};

function createResponse<T>(
    value: T | null
): DataResponse<T> | ErrorResponse {
    if (value !== null) {
        return {
            success: true,
            data: value
        };
    }
    return {
        success: false,
        errorMessage: "データが存在しません"
    };
}

const response1 = createResponse({ id: 1, name: "太郎" });
const response2 = createResponse(null);

この例では、ジェネリクス、ユニオン型、交差型をすべて組み合わせています。成功時と失敗時で異なる構造を持つレスポンスを、安全に表現できている点がポイントです。successフラグによって処理を分岐させることで、TypeScriptの型ガードとも相性の良い設計になります。

このような書き方を身につけると、「条件によって返るデータが変わる」という状況でも、型の不安を感じることなく実装できるようになります。結果として、コードの可読性と保守性が向上し、バグの混入も防ぎやすくなります。

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

生徒

「ジェネリクスとユニオン型、交差型って別々の知識だと思っていましたが、組み合わせるとすごく実用的なんですね。」

先生

「そうですね。TypeScriptの型は、単体よりも組み合わせて使うことで本領を発揮します。」

生徒

「特に、返り値の型を安全に表現できるのが分かって、実務で使うイメージが湧きました。」

先生

「それは良い理解です。型が整理されると、コードそのものも読みやすくなりますよ。」

生徒

「これからは、anyで逃げずに、ジェネリクスとユニオン型・交差型で表現できないか考えてみます。」

先生

「その意識が大切です。型を味方につけて、安心して書けるTypeScriptコードを目指しましょう。」

カテゴリの一覧へ
新着記事
New1
TypeScript
TypeScriptでPromiseの型推論をマスター!非同期処理とasync/awaitの基礎講座
New2
JavaScript
JavaScriptプログラムの実行方法まとめ!ブラウザ・Node.js・コンソールの使い方
New3
JavaScript
JavaScriptのBigInt型とは?大きな整数の扱い方と活用例
New4
JavaScript
JavaScriptでスクロール位置を取得・操作する方法を完全解説!scrollTopなどDOM操作入門
人気記事
No.1
Java&Spring記事人気No1
JavaScript
JavaScriptのインストール方法まとめ!Windows・Mac・Linux別にステップ解説
No.2
Java&Spring記事人気No2
JavaScript
JavaScriptのクロージャーとは?仕組みと実践例をやさしく解説
No.3
Java&Spring記事人気No3
JavaScript
JavaScriptで新しい要素を作成する方法(createElement, appendChildなど)
No.4
Java&Spring記事人気No4
TypeScript
TypeScriptのプロジェクトをtscでビルドする基本操作を解説!初心者にもわかるステップバイステップ
No.5
Java&Spring記事人気No5
JavaScript
JavaScriptでフォーム要素を操作するDOMテクニックを初心者向けに徹底解説
No.6
Java&Spring記事人気No6
JavaScript
JavaScriptで親要素・子要素・兄弟要素を取得する方法を初心者向けに徹底解説
No.7
Java&Spring記事人気No7
TypeScript
TypeScriptでnull・undefinedを型ガードするテクニックを徹底解説!初心者でも理解できる安全なコードの書き方
No.8
Java&Spring記事人気No8
TypeScript
TypeScriptの始め方:開発環境の構築手順【初心者向け】