TypeScript 枚举(Enum)详解

目录

  1. 概述
  2. 基本用法
  3. 枚举类型
  4. 高级特性
  5. 最佳实践
  6. 注意事项

概述

枚举(Enum)是 TypeScript 中用于定义一组命名常量的特性。它可以帮助我们更好地组织和管理相关的常量值。

为什么使用枚举?

  • 提供更好的代码可读性
  • 限制变量的可能取值
  • 提供类型安全
  • 自动编号功能

基本用法

1. 数字枚举

// 基本数字枚举
enum Direction {
  Up,      // 0
  Down,    // 1
  Left,    // 2
  Right    // 3
}

// 设置起始值
enum StatusCode {
  OK = 200,
  NotFound = 404,
  Error = 500
}

// 使用枚举
let dir: Direction = Direction.Up;
let status: StatusCode = StatusCode.OK;

2. 字符串枚举

enum Color {
  Red = "RED",
  Green = "GREEN",
  Blue = "BLUE"
}

// 使用字符串枚举
let color: Color = Color.Red;
console.log(color);  // "RED"

3. 异构枚举

// 混合字符串和数字
enum Mixed {
  No = 0,
  Yes = "YES",
}

枚举类型

1. 常量枚举

// 使用 const 声明的枚举
const enum LoadingState {
  Idle = "IDLE",
  Loading = "LOADING",
  Success = "SUCCESS",
  Error = "ERROR"
}

// 编译后直接内联值
const state = LoadingState.Loading;  // 直接编译为: "LOADING"

2. 计算枚举

enum Calculated {
  A = 1,
  B = A * 2,
  C = B * 2,
  // 计算值
  D = Math.floor(Math.random() * 100),
  // 引用其他常量
  E = '123'.length
}

3. 反向映射

enum AccessMode {
  Read = 1,
  Write = 2,
  ReadWrite = Read | Write
}

// 数字枚举支持反向映射
console.log(AccessMode[1]);  // "Read"
console.log(AccessMode["Read"]);  // 1

高级特性

1. 联合枚举类型

enum TriState {
  True = 1,
  False = 0,
  Unknown = -1
}

// 使用联合类型
function processState(state: TriState) {
  switch (state) {
    case TriState.True:
      return "是";
    case TriState.False:
      return "否";
    case TriState.Unknown:
      return "未知";
  }
}

2. 枚举成员类型

enum ShapeKind {
  Circle,
  Square
}

interface Circle {
  kind: ShapeKind.Circle;
  radius: number;
}

interface Square {
  kind: ShapeKind.Square;
  sideLength: number;
}

// 使用枚举成员作为类型
function getArea(shape: Circle | Square): number {
  switch (shape.kind) {
    case ShapeKind.Circle:
      return Math.PI * shape.radius ** 2;
    case ShapeKind.Square:
      return shape.sideLength ** 2;
  }
}

3. 运行时枚举

enum ApiStatus {
  OK = 200,
  NotFound = 404,
  Error = 500
}

// 枚举在运行时是真实存在的对象
function isSuccessStatus(status: number): boolean {
  return status === ApiStatus.OK;
}

// 遍历枚举
function getEnumNames(enumObj: any): string[] {
  return Object.keys(enumObj).filter(key => isNaN(Number(key)));
}

最佳实践

1. 使用常量枚举提高性能

// 推荐:使用常量枚举
const enum HttpMethod {
  GET = "GET",
  POST = "POST",
  PUT = "PUT",
  DELETE = "DELETE"
}

// 避免:普通枚举会生成额外代码
enum HttpMethod {
  GET = "GET",
  POST = "POST",
  PUT = "PUT",
  DELETE = "DELETE"
}

2. 合理使用字符串枚举

// 好的实践:使用字符串枚举提高可读性
enum LogLevel {
  Debug = "DEBUG",
  Info = "INFO",
  Warn = "WARN",
  Error = "ERROR"
}

// 避免:数字枚举可能造成混淆
enum LogLevel {
  Debug,  // 0
  Info,   // 1
  Warn,   // 2
  Error   // 3
}

3. 使用枚举替代魔法字符串

// 不好的写法
function setUserRole(role: string) {
  if (role === "admin" || role === "user" || role === "guest") {
    // ...
  }
}

// 好的写法
enum UserRole {
  Admin = "admin",
  User = "user",
  Guest = "guest"
}

function setUserRole(role: UserRole) {
  // ...
}

注意事项

1. 枚举成员的不可变性

enum Weekday {
  Monday,
  Tuesday
}

// 错误:枚举成员是只读的
Weekday.Monday = 1;  // Error

2. 避免类型不安全的枚举用法

enum Status {
  Active = 1,
  Inactive = 2
}

// 不好的写法:允许任何数字
function processStatus(status: number) {
  // ...
}

// 好的写法:限制为枚举类型
function processStatus(status: Status) {
  // ...
}

3. 注意枚举的大小

// 避免创建过大的枚举
enum LargeEnum {
  Value1, Value2, Value3, // ... 数百个值
}

// 考虑使用常量对象
const Constants = {
  Value1: 0,
  Value2: 1,
  Value3: 2,
} as const;

总结

  1. 枚举的优点:
  • 提供类型安全
  • 改善代码可读性
  • 自动编号功能
  • 支持反向映射
  1. 使用场景:
  • 状态管理
  • API 状态码
  • 配置选项
  • 权限控制
  1. 最佳实践:
  • 优先使用常量枚举
  • 合理选择字符串或数字枚举
  • 避免魔法字符串
  • 保持枚举简洁
    大白话:限制你输入的值值只能是那几种