TypeScript interface vs type 深度比較
interface 和 type 都能定義物件類型,但它們有些微妙的差異。本篇將深入比較,幫你做出正確選擇。
一、 基本語法
1.1 interface
typescript
interface User {
name: string
age: number
email?: string
}
const user: User = {
name: 'John',
age: 30,
}1.2 type
typescript
type User = {
name: string
age: number
email?: string
}
const user: User = {
name: 'John',
age: 30,
}結論:基本用法幾乎一樣!
二、 擴展方式
2.1 interface 用 extends
typescript
interface Animal {
name: string
}
interface Dog extends Animal {
breed: string
}
const dog: Dog = {
name: 'Buddy',
breed: 'Golden Retriever',
}多重繼承:
typescript
interface Runnable {
run(): void
}
interface Swimmable {
swim(): void
}
interface Dog extends Animal, Runnable, Swimmable {
breed: string
}2.2 type 用交叉類型 (&)
typescript
type Animal = {
name: string
}
type Dog = Animal & {
breed: string
}
const dog: Dog = {
name: 'Buddy',
breed: 'Golden Retriever',
}多重組合:
typescript
type Runnable = {
run(): void
}
type Swimmable = {
swim(): void
}
type Dog = Animal &
Runnable &
Swimmable & {
breed: string
}三、 Declaration Merging
3.1 interface 可以合併
typescript
interface User {
name: string
}
interface User {
age: number
}
// 自動合併成:
// interface User {
// name: string
// age: number
// }
const user: User = {
name: 'John',
age: 30,
}這在擴展第三方庫時很有用:
typescript
// 擴展 Express 的 Request
declare global {
namespace Express {
interface Request {
user?: User
}
}
}3.2 type 不能合併
typescript
type User = {
name: string
}
// 錯誤!重複定義
// type User = {
// age: number
// }四、 type 獨有功能
4.1 聯合類型
typescript
// type 可以
type Status = 'pending' | 'success' | 'error'
type ID = string | number
// interface 不能
// interface Status = 'pending' | 'success' | 'error'4.2 元組類型
typescript
// type 可以
type Point = [number, number]
type Response = [number, string, object]
// interface 寫起來很彆扭
interface Point {
0: number
1: number
length: 2
}4.3 映射類型
typescript
type Keys = 'name' | 'age' | 'email'
// type 可以
type User = {
[K in Keys]: string
}
// interface 不能直接使用映射類型4.4 條件類型
typescript
// type 可以
type IsString<T> = T extends string ? true : false
type A = IsString<string> // true
type B = IsString<number> // false
// interface 不能五、 interface 獨有功能
5.1 implements(類別實作)
typescript
interface Printable {
print(): void
}
// 兩者都可以被 implements
class Document implements Printable {
print() {
console.log('Printing...')
}
}其實
type也可以被implements,但interface更語義化。
5.2 更好的錯誤訊息
typescript
interface User {
name: string
age: number
}
// interface 的錯誤訊息通常更友好
const user: User = {
name: 'John',
// 缺少 age,錯誤訊息會明確指出
}六、 效能考量
6.1 interface 效能較好
typescript
// interface 在類型檢查時效能較好
// 因為 TypeScript 可以快取 interface
interface User {
name: string
}
// type 每次都需要重新計算
type User = {
name: string
}6.2 複雜類型組合
typescript
// 大量交叉類型可能影響效能
type ComplexType = A & B & C & D & E & F & G & H & I & J
// interface extends 效能較好
interface ComplexInterface extends A, B, C, D, E, F, G, H, I, J {}七、 何時用哪個?
7.1 使用 interface
| 場景 | 原因 |
|---|---|
| 定義物件形狀 | 語義明確 |
| 需要擴展 | extends 更清晰 |
| 類別實作 | implements |
| 第三方庫擴展 | Declaration Merging |
| 效能敏感 | 較快 |
7.2 使用 type
| 場景 | 原因 |
|---|---|
| 聯合類型 | 只能用 type |
| 元組類型 | 更直觀 |
| 映射類型 | 只能用 type |
| 條件類型 | 只能用 type |
| 原始類型別名 | type ID = string |
7.3 決策流程圖
八、 實用範例
8.1 API 回應(推薦 interface)
typescript
interface ApiResponse<T> {
success: boolean
data: T
error?: string
}
interface User {
id: number
name: string
}
interface PaginatedResponse<T> extends ApiResponse<T[]> {
pagination: {
page: number
total: number
}
}8.2 狀態管理(推薦 type)
typescript
type Status = 'idle' | 'loading' | 'success' | 'error'
type State =
| { status: 'idle' }
| { status: 'loading' }
| { status: 'success'; data: User }
| { status: 'error'; error: string }8.3 混合使用
typescript
// interface 定義物件
interface User {
id: number
name: string
status: UserStatus
}
// type 定義聯合類型
type UserStatus = 'active' | 'inactive' | 'banned'
// type 定義函式類型
type UserHandler = (user: User) => void總結
| 特性 | interface | type |
|---|---|---|
| 物件類型 | ||
| 擴展方式 | extends | & |
| Declaration Merging | ||
| 聯合類型 | ||
| 元組類型 | 彆扭 | |
| 映射類型 | ||
| 條件類型 | ||
| 效能 | 較好 | 一般 |
> **簡單規則**:
- 物件 →
interface - 其他 →
type - 不確定 →
interface(可以之後改)
進階挑戰
將以下需求用適當的方式定義:
typescript
// 1. API 回應格式
// 2. 表單狀態:idle | editing | submitting | error
// 3. 商品類型,需要之後擴展
// 4. 3D 座標 [x, y, z]
// 5. 可以是 string 或 string[]