【TypeScript】高度な型システム: 条件付き型とオーバーロード

TypeScript

TypeScriptは、型安全性を提供しながら柔軟性を保つ強力な型システムを備えています。
基本的な型システムについては入門編で紹介していますが、より高度な型や応用的な機能もあります。

本記事では、その中でも特に重要な「条件付き型」と「関数のオーバーロード」について詳しく解説します。

条件付き型

条件付き型とは、型の条件によって異なる型を導き出す仕組みであり、型の柔軟性をさらに向上させます。

条件付き型は、以下の構文で利用されます。

T extends U ? X : Y
  • T:チェック対象の型
  • U:条件となる型
  • X:条件が成立した場合の型
  • Y:条件が成立しない場合の型

基本的な例

以下のサンプルコードは、 IsString型を条件付き型で定義した例です。

type IsString<T> = T extends string ? "Yes" : "No";

type Test1 = IsString<string>; // "Yes"
type Test2 = IsString<number>; // "No"

この例では、型 Tstring かどうかに応じて結果を返しています。

実践的な応用例

以下は、配列の要素型を抽出するユーティリティ型 ElementType を作るサンプルです。
infer を使うことで、条件付き型内で型の推論を行い、柔軟な型変換が可能になります。

type ElementType<T> = T extends (infer U)[] ? U : never;

type TestArray = ElementType<number[]>; // number
type TestNonArray = ElementType<string>; // never

infer とは、TypeScriptの条件付き型の中で使用される特殊なキーワードで、型から部分的な情報を推論するためのものです。

infer の基本的な構文は次の通りです。

T extends SomeType<infer U> ? X : Y
  • SomeType<infer U>:チェック対象の型 T が SomeType にマッチする場合に、infer U を用いて型 U を推論します。

関数のオーバーロード

関数のオーバーロードは、引数の数または引数の型が異なるという条件を満たす同名の関数を定義できる仕組みです。

オーバーロードの基本ルール

  • 引数の型や、あるいは数が異なる関数シグネチャを同じ名前で定義できる。
    • シグネチャの引数型や数が異なることで、関数の挙動を切り替えられる。
  • 戻り値の型はオーバーロード条件にならない。
    • 戻り値型のみが異なる(引数の数と型が同じ)場合は、オーバーロードとして認識されない。
  • 実装される関数は1つだけ。
    • ここがJavaのオーバーロードとの相違点
    • 実装部分で全てのシグネチャをカバーする形を取る。

基本的な使い方

以下は、異なる型の入力を処理するユーティリティ関数を作成するサンプルです。
string型またはnumber型の入力に対して異なる処理を行います。

function process(value: string): Date; // 文字列を受け取り、Date型を返す
function process(value: number): string; // 数値を受け取り、文字列を返す
function process(value: any): any {
  if (typeof value === "string") {
    return new Date(value); // 文字列を日付に変換
  } else if (typeof value === "number") {
    return value.toString(); // 数値を文字列に変換
  }
}

const result1 = process("2025-03-26"); // Date型
const result2 = process(123); // string型

この例では、呼び出し側の引数型に応じて、適切な関数シグネチャが選択されます。

まとめ

本記事では、「条件付き型」と「オーバーロード」について解説しました。
それぞれの概要を以下にまとめます。

条件付き型

条件付き型は、型の条件によって動的に異なる型を導き出す仕組みを提供します。以下のポイントが特徴です。

  • T extends U? X : Y」の構文を使用し、型に応じた分岐処理を実現。
  • infer を活用して型の部分推論が可能。
  • 動的な型変換やチェックを効率的に行える。

オーバーロード

オーバーロードは、異なる引数型や数に応じた特定の関数挙動を実現する機能です。

  • 複数のシグネチャを定義することで、型安全性を高めながら柔軟な設計を可能にする。
  • TypeScript特有の設計として、単一の実装で全シグネチャをカバーする必要がある。
  • Javaとの共通点: 引数型や数が異なることが必須条件であり、戻り値型のみではオーバーロードを区別できない。

本記事についての質問、誤りの指摘、ご意見ご感想などありましたら、ぜひコメント頂ければ幸いです。

最後までお読みいただき、ありがとうございます。

コメント

タイトルとURLをコピーしました