type 和 interface 誰才是最佳選擇?
前言
在開始學習 TypeScript 時,我們很快就會接觸到 type
和 interface
這兩種型別定義方式。看起來它們都能描述物件,甚至在許多情境下可以互換使用。但讓很多初學者感到疑惑的是:
「在這個情況下,我到底應該用 type 還是 interface?」
我自己一直以來都沒有特別在意什麼時候該用 type,什麼時候該用 interface,直到最近在維護舊專案時,發現這樣隨意交錯使用 type 和 interface 讓我的程式碼的可讀性變得很差,因此決定稍微研究一下 type 和 interface 的差異,幫助我未來在決定使用任一者時,有個比較明確的準則。
type
與 interface
語法比較
以下是 type
和 interface
在不同功能上的對比:
type | interface | |
---|---|---|
物件型別定義 | ✅ | ✅ |
擴展(繼承)型別 | & (交集) | extends |
可定義聯合型別(Union) | ✅ | ❌ |
可定義基本型別(如 string 、number ) | ✅ | ❌ |
可定義元組(Tuple) | ✅ | ❌ |
可多次定義(會自動合併) | ❌ | ✅ |
可用於 class implements | ⚠️ | ✅ |
1️⃣ 物件型別的基本定義
使用 type
type User = {
name: string;
age: number;
};
使用 interface
interface User {
name: string;
age: number;
}
無論 type
還是 interface
,最基本的用途都是用來定義物件型別,這兩種方式在這種簡單的物件型別定義上完全等價,但當我們需要進一步擴展型別時,兩者就開始出現不同了。
2️⃣ 型別擴展(繼承)
使用 interface extends
interface
使用 extends
來擴展另一個 interface
:
interface User {
name: string;
age: number;
}
interface Admin extends User {
role: string;
}
const admin: Admin = {
name: "Alice",
age: 30,
role: "superadmin",
};
這種方式 更接近物件導向設計,類似於 class
的繼承。
使用 type &
type
使用 交集(Intersection Type,&
) 來合併型別:
type User = {
name: string;
age: number;
};
type Admin = User & { role: string };
const admin: Admin = {
name: "Alice",
age: 30,
role: "superadmin",
};
雖然 &
和 extends
的結果在這裡看起來一樣,但 &
可以用來合併任何型別,不只限於物件,這是 type
更靈活的地方。
3️⃣ type
可以定義聯合型別
這是 type
最大的優勢之一,它可以定義「多種可能性」的型別,而 interface
則不行。
type
定義聯合型別
type Status = "success" | "error" | "loading";
let currentStatus: Status;
currentStatus = "success"; // ✅ 合法
currentStatus = "loading"; // ✅ 合法
currentStatus = "failed"; // ❌ 錯誤,因為 "failed" 不是 Status 的成員
warning
interface
只能描述物件,不能像 type
一樣定義基本型別或聯合型別。