TypeScript 速習チュートリアル

TypeScript ジェネリクスの基本

ジェネリクス(Generics)を使用すると、使用する型を明示的に定義することなく「型変数(Type Variables)」を作成できます。これにより、クラス、関数、型エイリアスを、使用する型を固定せずに作成することが可能になります。ジェネリクスは、再利用性の高いコードを書くための強力なツールです。

1. 関数におけるジェネリクス

関数でジェネリクスを使用すると、入力値(引数)と戻り値の型を正確に表現した、より汎用的な関数を作成できます。

function createPair<S, T>(v1: S, v2: T): [S, T] {
  return [v1, v2];
}
// 文字列と数値のペアを作成
console.log(createPair<string, number>('hello', 42)); // ['hello', 42]

また、TypeScript は関数の引数からジェネリクスパラメータ(Generic Parameter)の型を推論(Infers)することも可能です。

2. クラスにおけるジェネリクス

ジェネリクスを使用して、Map のような汎用化されたクラスを作成できます。

class NamedValue<T> {
  private _value: T | undefined;

  constructor(private name: string) {}

  public setValue(value: T) {
    this._value = value;
  }

  public getValue(): T | undefined {
    return this._value;
  }

  public toString(): string {
    return `${this.name}: ${this._value}`;
  }
}

// 数値型(number)を扱うインスタンスを作成
let value = new NamedValue<number>('myNumber');
value.setValue(10);
console.log(value.toString()); // myNumber: 10

ジェネリクスパラメータがコンストラクタ(Constructor)の引数で使用されている場合、TypeScript はその型を推論できます。

3. 型エイリアスにおけるジェネリクス

型エイリアス(Type Aliases)でジェネリクスを使用すると、より再利用可能な型を作成できます。

type Wrapped<T> = { value: T };

const wrappedValue: Wrapped<number> = { value: 10 };

これはインターフェース(Interfaces)でも同様の構文 interface Wrapped<T> { ... } で機能します。

4. デフォルト値 (Default Value)

ジェネリクスにはデフォルト値(Default Values)を割り当てることができます。これは、他の値が指定されなかったり、推論できなかったりした場合に適用されます。

class NamedValue<T = string> {
  private _value: T | undefined;

  constructor(private name: string) {}

  public setValue(value: T) {
    this._value = value;
  }

  public getValue(): T | undefined {
    return this._value;
  }

  public toString(): string {
    return `${this.name}: ${this._value}`;
  }
}

// 型を指定しない場合、デフォルトの string 型が適用されます
let value = new NamedValue('myNumber');
value.setValue('myValue');
console.log(value.toString()); // myNumber: myValue

5. 型制約 (Extends)

ジェネリクスに制約(Constraints)を追加して、許容される型を制限することができます。
制約を設けることで、ジェネリクス型を使用する際により特定の型に基づいたプロパティやメソッドに依存することが可能になります。

// S と T が string または number のいずれかであることを強制する制約
function createLoggedPair<S extends string | number, T extends string | number>(v1: S, v2: T): [S, T] {
  console.log(`ペアを作成中: v1='${v1}', v2='${v2}'`);
  return [v1, v2];
}

この型制約は、デフォルト値と組み合わせて使用することも可能です。