TypeScript ジェネリックの例

TypeScript ジェネリックは、再利用可能で型安全なコンポーネントを作成できる強力な機能です。ジェネリックを使用すると、強力な型安全性を維持しながら、さまざまな型で動作するクラス、関数、およびインターフェイスを作成できます。この記事では、ジェネリックについて紹介し、実際の例を使用してジェネリックの使用方法を説明します。

ジェネリックを理解する

ジェネリックを使用すると、操作対象の型のプレースホルダーを使用してコンポーネントを定義できます。具体的な型を指定する代わりに、コンポーネントの使用時に任意の型に置き換えることができるジェネリック型パラメーターを使用します。

基本的な構文

ジェネリック型を定義するための基本的な構文は、型パラメータ名とともに山括弧 <> を使用することです。次に簡単な例を示します。

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

const stringIdentity = identity("Hello"); // string
const numberIdentity = identity(123); // number

この例では、identity は、型 T のパラメーター value を受け取り、同じ型の値を返す汎用関数です。型パラメーター T は、関数が呼び出されたときに実際の型に置き換えられます。

クラス付きジェネリック

ジェネリックはクラスと組み合わせて使用​​して、柔軟で再利用可能なデータ構造を作成することもできます。ジェネリック クラスの例を次に示します。

class Box {
  private value: T;

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

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

const stringBox = new Box("TypeScript");
console.log(stringBox.getValue()); // Output: TypeScript

const numberBox = new Box(42);
console.log(numberBox.getValue()); // Output: 42

この例では、Box クラスはジェネリック型パラメータ T を使用して定義されています。このクラスには、型 T のプライベート プロパティ value と、型 T の値を返すメソッド getValue があります。

インターフェース付きジェネリック

ジェネリックをインターフェースと組み合わせて使用​​すると、柔軟で型安全なインターフェースを作成できます。次に例を示します。

interface Pair<T, U> {
  first: T;
  second: U;
}

const pair: Pair<string, number> = {
  first: "Age",
  second: 30
};

console.log(pair.first); // Output: Age
console.log(pair.second); // Output: 30

この例では、Pair インターフェイスは、2 つのジェネリック型パラメータ TU を使用して定義されています。インターフェイスは、それぞれ T 型と U 型の値のペアを表します。

関数内のジェネリック

ジェネリックは関数内で使用して、型の安全性を維持しながら複数の型を処理できます。以下は配列で動作するジェネリック関数の例です。

function reverseArray(items: T[]): T[] {
  return items.reverse();
}

const reversedStringArray = reverseArray(["one", "two", "three"]);
console.log(reversedStringArray); // Output: ["three", "two", "one"]

const reversedNumberArray = reverseArray([1, 2, 3]);
console.log(reversedNumberArray); // Output: [3, 2, 1]

この例では、reverseArray 関数は T 型の配列を受け取り、同じ型の反転された配列を返します。型パラメータ T により、関数は型の安全性を維持しながら、任意の型の配列で動作することが保証されます。

ジェネリックの制約

場合によっては、ジェネリック型パラメータに特定のプロパティを持たせるために制約を課す必要があることがあります。これは制約を使用して行います。

function logLength(item: T): void {
  console.log(item.length);
}

logLength("Hello, TypeScript"); // Output: 16
logLength([1, 2, 3]); // Output: 3
// logLength(123); // Error: number does not have a length property

この例では、logLength 関数は、length プロパティを持つ型に制限されています。これにより、関数は文字列と配列を受け入れることができますが、数値や length プロパティを持たない他の型は受け入れることができません。

結論

TypeScript のジェネリックは、強力な型安全性を維持しながら、柔軟で再利用可能なコンポーネントを作成する強力な方法を提供します。ジェネリックを理解して活用することで、より汎用的で適応性の高いコードを記述でき、TypeScript アプリケーションの全体的な品質と保守性が向上します。

プロジェクトでジェネリックを試して、そのメリットを実際に確認し、TypeScript プログラミング スキルを向上させましょう。