typeinterface 的區別與優缺點

interface 的優缺點

優點:

  • 可以擴展和合併

    • 可以通過 extends 來繼承其他介面

    • 支援多次宣告同一個 interface, 並自動合併屬性 (宣告合併)

interface Person {
  name: string;
}

interface Person {
  age: number;
}

const person: Person = { name: "David", age: 30 }; // 宣告合併
  • 語義清晰

    • 更接近物件導向中的 class, 能清晰表達一個物件的結構
  • 被推薦使用

    • 官方建議使用 interface 來定義物件的結構, 特別是在定義 API 模型時

缺點:

  • 不能直接定義聯合型別

    • 不支持直接定義聯合型別 (Union Types), 但可以通過 擴展交集 型別等來間接達成

type 的優缺點

優點:

  • 更靈活

    • 可以用來定義聯合型別、交集型別、元組 (Tuple) 等, 比 interface 更靈活
type Status = "success" | "error" | "loading"; // 聯合型別
type Person = { name: string } & { age: number }; // 交集型別
  • 可以定義非物件型別

    • type 可以定義原始類型 (如 stringnumber)、聯合型別等

缺點:

  • 無法合併型別

    • type 無法像 interface 一樣進行宣告合併
  • 可讀性較差

    • 當處理複雜的型別結構時, type 的靈活性可能會導致可讀性變差

何時使用 type or interface?

  • 使用 interface

    • 需要定義物件的 結構, 並且可能會在 多處擴展這個型別 的時候
  • 使用 type

    • 需要 定義 聯合型別、交集型別或其他複雜的型別操作的時候

    • 需要 統整多種類型 的資料的時候, type 提供了更好的靈活性

使用 type 和 interface 統整型別

使用 interface 進行交集型別:

export interface Human {
  alive: boolean;
}

export interface User {
  age: number;
}

export interface User {
  name: "Jess" | "Lucy";
}
// User 會被自動合併,最終結構是 { age: number; name: "Jess" | "Lucy" }

// Human & User 來表示同時具有 Human 和 User 屬性的物件
const user1: Human & User = {
  age: 23,
  name: "Jess",
  alive: true,
};

使用 type 進行聯合型別:

// type UserInfo 是 MaleUser 和 FemaleUser 的聯合型別,因此可以表示 MaleUser 或 FemaleUser 中的任何一種
type UserInfo = MaleUser | FemaleUser;

export type MaleUser = {
  age: number;
  name: "Jess" | "David";
};

export interface FemaleUser {
  age: number;
  pregnant: boolean;
}

export interface FemaleUser {
  name: "Lucy";
}

const user: UserInfo = { age: 18, pregnant: false, name: "Lucy" };

if ("pregnant" in user) {
  console.log(user.pregnant); // user 的型別是 FemaleUser
}

總結

  • type 用於定義複雜的型別操作, 支持聯合型別、交集型別等

  • interface 則適合用來定義物件的結構, 且具有合併和擴展的特性

根據需求選擇 interfacetype 也可以據情況結合使用