iT邦幫忙

2025 iThome 鐵人賽

DAY 6
0

昨天我們聊了物件型別,今天來認識 TypeScript 裡的 Enum(列舉型別)

它的使命很簡單:

幫一組相關的常數找一個統一管理的家。

當你的專案裡出現一大堆字串或數字常數,

就很容易打錯或忘記有哪些選項。

Enum(列舉)就是為了幫這些常數找個家。


1. 為什麼需要 Enum?

想像你有一組訂單狀態:

let status = "Created"; // 其他地方用 "Paid"
let anotherStatus = "Shipped"; // 還有人打成 "Shiped"(typo)

問題

  • 值是字串,容易打錯
  • 無法限制只能用這幾個狀態

解法:用 Enum 定義規範。


2. 基本用法

enum Direction {
  Up,
  Down,
  Left,
  Right
}

let move: Direction = Direction.Up;

預設會從 0 開始編號,Direction.Up = 0,Direction.Down = 1...


3. 自訂值

你可以手動指定 Enum 的值,常用於 API 或有業務意義的數值:

enum Role {
  Admin = "ADMIN",
  User = "USER",
  Guest = "GUEST"
}


4. 反向查詢(只適用數字 Enum)

數字 Enum 在編譯後會同時支援「由值找鍵」:

enum Status {
  Success = 200,
  NotFound = 404
}

console.log(Status.Success); // 200
console.log(Status[200]);    // "Success"

注意:字串 Enum 沒有這功能。


5. 常數列舉(const enum)

效能優化:編譯後會直接用值取代,不保留對象結構。

const enum HttpStatus {
  OK = 200,
  NotFound = 404
}

let code = HttpStatus.OK; // 編譯後直接變成 200

優點:少一層存取

缺點:不能做反向查詢


6. Enum 的實務應用場景

API 狀態管理

enum OrderStatus {
  Created = "CREATED",
  Paid = "PAID",
  Shipped = "SHIPPED",
  Cancelled = "CANCELLED"
}

function getOrderStatusText(status: OrderStatus) {
  switch (status) {
    case OrderStatus.Created:
      return "訂單已建立";
    case OrderStatus.Paid:
      return "已付款";
    case OrderStatus.Shipped:
      return "已出貨";
    case OrderStatus.Cancelled:
      return "已取消";
  }
}

權限控管

enum Permission {
  Read = 1 << 0,
  Write = 1 << 1,
  Execute = 1 << 2
}

let userPermission = Permission.Read | Permission.Write;


7. Enum vs Literal Union

有時候你會發現,用字面量聯合型別也能做到類似效果:

type OrderStatusLiteral = "CREATED" | "PAID" | "SHIPPED" | "CANCELLED";

差異

  • Enum:在編譯後依然存在(可用在 JS runtime)
  • Literal Union:只在編譯期存在,編譯後就是字串

如果你需要在 程式執行時 取到 Enum 值,用 Enum。如果只是做型別檢查,用 Union 較輕量。


8. 常見陷阱

  • 數字 Enum 如果中間有手動指定值,後面會依序加:
enum Test {
  A = 1, // 1
  B,     // 2
  C      // 3
}

  • 字串 Enum 不能自動遞增,全部都要手動指定值

上一篇
Day 5|物件型別:讓你的物件有「契約精神」
下一篇
Day 7|型別推論:TS 比你想像的還聰明
系列文
我與型別的 30 天約定:TypeScript 入坑實錄12
圖片
  熱門推薦
圖片
{{ item.channelVendor }} | {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言