TypeScript 聯合與交集型別 (Union and Intersection Types)

想像你在咖啡廳點餐:

  • 「我要咖啡茶」 -> 這就是聯合型別 (Union),二選一。
  • 「我要一杯又冰又甜的飲料」 -> 這就是交集型別 (Intersection),兩個條件都要滿足。

1. 聯合型別 (Union Types) - 「或」 (OR)

使用 | 符號。這是 TypeScript 最強大的功能之一,它允許一個變數擁有多種身分。

// 變數可以是字串,也可以是數字
let id: string | number;

id = 'A123'; // OK
id = 101; // OK
// id = true;   // 錯誤

為什麼需要它?

在 JavaScript 中,一個函式常常可以接受不同類型的參數。

function printId(id: string | number) {
  // 這裡我們只知道 id 是 string 或 number
  // 所以只能用它們「共有」的方法 (如 .toString())
  console.log('Your ID is: ' + id.toString());

  // 如果要用特有方法,必須先「收窄 (Narrowing)」
  if (typeof id === 'string') {
    // 這裡 id 被收窄為 string,可以用 toUpperCase
    console.log(id.toUpperCase());
  } else {
    // 這裡 id 被收窄為 number
    console.log(id.toFixed(2));
  }
}

2. 交集型別 (Intersection Types) - 「且」 (AND)

使用 & 符號。它把多個型別「合併」成一個新的型別,這個新型別必須同時擁有所有型別的特徵

這常混淆很多人,因為 & 看起來像是集合論的「交集」,但對物件來說,它比較像是「聯集」(把屬性加在一起)。

interface Draggable {
  drag: () => void;
}

interface Resizable {
  resize: () => void;
}

// UIComponent 必須「同時」具備 Draggable 和 Resizable 的能力
type UIComponent = Draggable & Resizable;

const box: UIComponent = {
  drag: () => {},
  resize: () => {},
};

陷阱:不可能的交集

如果你試圖把互斥的型別交集在一起,會得到 never (不可能存在的型別)。

// 世界上沒有一個值既是 string 又是 number
type Impossible = string & number; // 結果是 never

總結

符號名稱意義記憶口訣
|Union (聯合)A 或 B選一個 (像是菜單點餐)
&Intersection (交集)A 且 B全都要 (像是全能超人)