前言
在 TypeScript 中,type 和 interface 都可以用來定義型別,但它們有各自的特點和適用場景。這篇文章將詳細比較兩者的差異,幫助你做出正確的選擇。
type 和 interface 的區別與優缺點
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更靈活
- 可以用來定義聯合型別、交集型別、元組(Tuple)等,比
type Status = "success" | "error" | "loading"; // 聯合型別
type Person = { name: string } & { age: number }; // 交集型別
- 可以定義非物件型別
- type 可以定義原始類型(如
string、number)、聯合型別等
- type 可以定義原始類型(如
缺點:
- 無法合併型別
type無法像interface一樣進行宣告合併
- 可讀性較差
- 當處理複雜的型別結構時,
type的靈活性可能會導致可讀性變差
- 當處理複雜的型別結構時,
何時使用 type 或 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 取決於你的需求:
type:用於定義複雜的型別操作,支持聯合型別、交集型別等interface:適合用來定義物件的結構,且具有合併和擴展的特性
在實際開發中,可以根據情況結合使用兩者,發揮各自的優勢。