跳至主要內容
Skip to content

TypeScript interface vs type 深度比較

interfacetype 都能定義物件類型,但它們有些微妙的差異。本篇將深入比較,幫你做出正確選擇。


一、 基本語法

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

總結

特性interfacetype
物件類型
擴展方式extends&
Declaration Merging
聯合類型
元組類型彆扭
映射類型
條件類型
效能較好一般

> **簡單規則**:

  • 物件 → interface
  • 其他 → type
  • 不確定 → interface(可以之後改)

進階挑戰

將以下需求用適當的方式定義:

typescript
// 1. API 回應格式
// 2. 表單狀態:idle | editing | submitting | error
// 3. 商品類型,需要之後擴展
// 4. 3D 座標 [x, y, z]
// 5. 可以是 string 或 string[]

延伸閱讀與資源