TypeScript 速習チュートリアル

TypeScript 型エイリアスとインターフェース

TypeScriptでは、変数から切り離して独立した「型」を定義することができます。
型エイリアス(Type Aliases)インターフェース(Interfaces)を利用することで、異なる変数やオブジェクト間で型を簡単に共有・再利用できるようになります。

1. 型エイリアス (Type Aliases)

型エイリアスを使用すると、任意の型にカスタム名(別名)を付けることができます。
string のようなプリミティブ型から、objectarray のような複雑な型まで幅広く対応可能です。

例:基本的な型エイリアス

type CarYear = number;
type CarType = string;
type CarModel = string;
type Car = {
  year: CarYear,
  type: CarType,
  model: CarModel
};

const carYear: CarYear = 2001;
const carType: CarType = "トヨタ";
const carModel: CarModel = "カローラ";
const car: Car = {
  year: carYear,
  type: carType,
  model: carModel
};

例:ユニオン型とインターセクション型

// インターセクション型(型の結合)
type Animal = { name: string };
type Bear = Animal & { honey: boolean };
const bear: Bear = { name: "プーさん", honey: true };

// ユニオン型(複数の候補から選択)
type Status = "success" | "error";
let response: Status = "success";

2. インターフェース (Interfaces)

インターフェースは型エイリアスに似ていますが、オブジェクト型(Object types)にのみ適用されるという特徴があります。

例:インターフェースの定義

interface Rectangle {
  height: number,
  width: number
}

const rectangle: Rectangle = {
  height: 20,
  width: 10
};

例:インターフェースの結合(Interface Merging)
インターフェースは同じ名前で複数回宣言すると、自動的にマージされます。

interface Animal { name: string; }
interface Animal { age: number; }

// 両方のプロパティが必要になる
const dog: Animal = { name: "フィド", age: 5 };

3. Type と Interface の主な違い

特徴型エイリアス (Type)インターフェース (Interface)
拡張 (Extending)インターセクション(&)で可能extends キーワードで可能。宣言の結合もサポート
ユニオン/インターセクションサポートしているサポートしていない(Objectのみ)
クラスへの実装可能可能

       推奨事項: オブジェクトの形状を定義する場合は interface を使い、それ以外のケース(ユニオン型やプリミティブの別名など)には type を使うのが一般的です。

4. ベストプラクティス

  • オブジェクトの構造やパブリックAPIを定義する際は interface を使用する。
  • ユニオン型、インターセクション型、またはプリミティブ型の別名が必要な場合は type を使用する。
  • 型の継承(Inheritance)よりもコンポジション(Composition:合成)を優先する。
  • 可読性を高めるために、型やインターフェースには適切なドキュメント(コメント)を残す。

5. よくある落とし穴

  • 宣言の結合(Declaration Merging)が必要な場面で type を使ってしまう(その場合は interface が適切)。
  • 型を複雑にしすぎる(シンプルかつ特定の責務にフォーカスした定義を心がける)。
  • コードの進化に合わせて型やインターフェースの更新を忘れてしまう。

6. インターフェースの拡張 (Extending Interfaces)

インターフェースは、他のインターフェースの定義を拡張することができます。
拡張することで、元のプロパティをすべて引き継ぎつつ、新しいプロパティを追加した新しいインターフェースを作成できます。

例:インターフェースの拡張

interface Rectangle {
  height: number,
  width: number
}

// Rectangleを拡張して新しいプロパティを追加
interface ColoredRectangle extends Rectangle {
  color: string
}

const coloredRectangle: ColoredRectangle = {
  height: 20,
  width: 10,
  color: "赤"
};