0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

[TypeScript学習記録] typeとInterfaceとは

Last updated at Posted at 2025-05-10

TypeScriptにおける type(型エイリアス)と interface は、どちらも型を定義するための構文で、オブジェクトやデータの構造を記述する際に使用される。

1. typeとは

typeは、型エイリアス(型の別名)を作成する構文で、特定の型や値の構造に名前を付けて再利用可能にできる。オブジェクト型だけでなく、プリミティブ型、ユニオン型、交差型、リテラル型など、幅広い型を定義可能。

特徴

  • 単一定義:同じ名前での再定義は不可(上書きできない)。
  • 演算子を使用|(ユニオン)や&(交差)で型を組み合わせ可能。
  • ジェネリクス対応:型パラメータをサポート。

サンプルコード

// オブジェクト型の定義
type User = {
  id: number;
  name: string;
  email?: string;
};

const user: User = { id: 1, name: "Alice" };

// ユニオン型の定義
type ID = number | string;
let userId: ID = "abc123";

// 交差型の定義
type Point = { x: number } & { y: number };
const point: Point = { x: 10, y: 20 };

// リテラル型の定義
type Status = "success" | "error";
let status: Status = "success";

ユースケース

  • プリミティブ型やユニオン型を定義(例:type Role = "admin" | "user")。
  • 複雑な型操作(例:交差型やジェネリクス)。
  • 一時的な型や単発の型定義。

2. interfaceとは

interfaceは、オブジェクトやクラスの構造を定義するための構文で、主にオブジェクトの形状クラスの契約を記述。TypeScriptの構造的型システムに基づき、特定のプロパティやメソッドを持つ型を保証。

特徴

  • オブジェクト/クラス特化:主にオブジェクト型やクラスの型定義に使用。
  • マージ可能:同じ名前のinterfaceを複数定義すると、自動的にマージされる。
  • 継承対応extendsで他のインターフェースを拡張可能。
  • 実装対応implementsキーワードを使用して、インターフェースを実装。

サンプルコード

// 基本的なインターフェース
interface User {
  id: number;
  name: string;
  email?: string;
}

const user: User = { id: 1, name: "Alice" };

// インターフェースのマージ
interface User {
  role: string;
}

const admin: User = { id: 2, name: "Bob", role: "admin" }; // emailもroleも含む

// インターフェースの拡張
interface Admin extends User {
  permissions: string[];
}

const superAdmin: Admin = {
  id: 3,
  name: "Charlie",
  role: "superadmin",
  permissions: ["read", "write"],
};

// クラスの実装
interface Printable {
  print(): void;
}

class Document implements Printable {
  print() {
    console.log("Printing...");
  }
}

ユースケース

  • オブジェクトやクラスの構造を定義(例:APIレスポンス、コンポーネントのprops)。
  • 複数のモジュールでインターフェースを拡張(マージ)。
  • クラスやライブラリの型定義。

3. typeinterfaceの主な違い

比較項目 type interface
再定義 ❌ 不可 ⚪ マージされる
ユニオン型 ⚪ 対応 ❌ 非対応(オブジェクトに限られる)
交差型(合成) ⚪ &演算子で可能 ⚪ extends キーワードで可能
プリミティブ型 ⚪ 定義可能 ❌ 定義不可
クラス実装 ⚪ 可能 (implements不可) ⚪ implements で明示的に連携可能
マージ挙動 ❌ 上書きエラー ⚪ 自動的に統合

マージの例

// interface: マージされる
interface User {
  name: string;
}
interface User {
  age: number;
}
const user: User = { name: "Alice", age: 25 }; // OK

// type: マージ不可
type Point = { x: number };
// type Point = { y: number }; // エラー: 再定義不可

拡張の例

// interface: extendsで拡張
interface Person {
  name: string;
}
interface Employee extends Person {
  job: string;
}

// type: 交差型で拡張
type PersonType = { name: string };
type EmployeeType = PersonType & { job: string };

4. 使い分け

typeを選ぶ場合

  • プリミティブ型やユニオン型を定義
    type Role = "admin" | "user";
    type ID = number | string;
    
  • 複雑な型操作(ジェネリクス、交差型、ユーティリティ型など):
    type PartialUser = Partial<{ id: number; name: string }>;
    
  • 一時的または単発の型:再利用や拡張が不要な場合。
  • 柔軟性が欲しい:型エイリアスは幅広い型に対応。

interfaceを選ぶ場合

  • オブジェクト型やクラスの構造を定義
    interface User {
      id: number;
      name: string;
    }
    
  • マージが必要:ライブラリやモジュール間で型を拡張。
    interface Window {
      customProperty: string; // グローバル型を拡張
    }
    
  • クラス実装:クラスが特定のインターフェースを満たす必要がある場合。
    interface Printable {
      print(): void;
    }
    class Document implements Printable {
      print() {}
    }
    

注意点

意図しない型の競合に注意
複数のライブラリやスクリプトが同じインターフェース名を使っていると、型の競合が起きる。

// 意図しない競合例
interface Window {
  customProp: string;
}
interface Window {
  customProp: number; // ❌ 型の衝突が発生(エラー)
}

→ このような場合、衝突を避けるために type の使用やスコープ分離が推奨される。

まとめ

  • type:柔軟で、ユニオン型やプリミティブ型、複雑な型操作に最適。単一定義で再定義不可。
  • interface:オブジェクト型やクラスに特化。マージや継承が強力。
  • 使い分け:オブジェクト型や拡張性ならinterface、ユニオン型や一時的な型ならtype
0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?