今天我們要聊 TypeScript 裡常見的一個靈魂拷問:
物件型別要用 type 還是 interface?
初學者常覺得它們差不多,但其實有些關鍵差異,知道了之後你就能根據需求正確選擇。
用來為任何型別取一個名字,不只物件型別。
type User = {
name: string;
age: number;
};
它還能定義:
|
)&
)type ID = string | number;
type Point = [number, number];
type Add = (a: number, b: number) => number;
專門用來描述物件型別(以及 class 的結構)。
interface User {
name: string;
age: number;
}
它不能直接用來定義聯合型別、Tuple 等「非物件型別」。
功能/特性 | Type Alias | Interface |
---|---|---|
可描述物件型別 | ✅ | ✅ |
可描述聯合型別 | ✅ | ❌ |
可描述 Tuple | ✅ | ❌ |
擴展型別(extends / implements) | ❌(用交叉型別代替) | ✅(extends) |
可被多次宣告合併 | ❌ | ✅(Declaration Merging) |
適用場景 | 靈活、可定義任何型別 | 主要用於物件、Class 契約 |
type Person = { name: string };
type WithAge = Person & { age: number };
let p: WithAge = { name: "Alice", age: 25 };
extends
interface Person {
name: string;
}
interface WithAge extends Person {
age: number;
}
let p: WithAge = { name: "Bob", age: 30 };
Interface 有個很酷的功能:可以多次定義同名介面,會自動合併。
interface User {
name: string;
}
interface User {
age: number;
}
let u: User = { name: "Charlie", age: 20 };
Type 就不行:
type User = { name: string };
type User = { age: number }; // ❌ Duplicate identifier 'User'
type ApiResponse<T> = {
data: T;
status: number;
message: string;
};
interface Logger {
log(message: string): void;
}
class ConsoleLogger implements Logger {
log(message: string) {
console.log(message);
}
}