TypeScript8(枚举)

301 阅读4分钟

enum 是 TypeScript 提供的一个重要特性,它允许我们为一组数字或字符串定义一个更具描述性的名字。这使得代码更易读、更易于维护。

1.数字枚举

这是最常见的类型。默认情况下,枚举成员会被赋值为从 0 开始递增的数字。

enum Direction {
    Up,
    Down,
    Left,
    Right

}
let playerDirection = Direction.Up;
// console.log(playerDirection); // 0
// console.log(Direction.Right);// 3

//也可以手动为成员赋值,后面的值会自动递增
enum StatusCode {
    NotFound = 404,
    OK = 200,
    ServerError = 500,
    Created
}
// console.log(StatusCode.Created);// 501

2.字符串枚举

字符串枚举的成员必须都赋有字符串值。它的好处是,在调试时,打印出的值更具可读性。

enum DirectionString {
    Up = "UP",
    Down = "DOWN",
    Left = "LEFT",
    Right = "RIGHT"
}
// console.log(DirectionString.Up); // "UP"

3.异构枚举

枚举可以包含不同类型的成员。不推荐使用,可能会导致代码难以理解。

enum Status {
    OK = 'OK',
    Error = 1,
}

4.const枚举

如果你关心性能,并且确定枚举在编译后不需要作为一个对象存在,可以使用 const enum

const enum Color { Red, Green, Blue }

特点:

  • 编译时内联:在编译后,所有对 const enum 成员的引用都会被替换为其具体的值。例如,Color.Red 会直接被替换为 0
  • 无运行时对象:编译后的 JavaScript 代码中不会存在 Color 这个对象,这可以减少代码体积
  • 无反向映射:由于编译后对象不存在,自然也不支持反向映射。

5.数字,字符串,常量枚举之间的对比

特性数字枚举字符串枚举常量枚举
成员值数字字符串数组或字符串
反向映射✔支持❌不支持❌不支持
运行时对象✔生成✔生成❌不生成
可读性一般非常好
性能一般一般非常好
场景与旧有代码或外部系统(需要数字)交互需要高可读性和明确性的场景(如日志、状态码)性能敏感、不需要运行时访问枚举对象的场景

6.反向映射

反向映射是数字枚举的独特之处,它允许我们 通过枚举的值(value)来反向获取其对应的成员名(key)

enum Direction {
  Up,    // 0
  Down,  // 1
  Left,  // 2
  Right  // 3
}

// 反向映射:从值到成员名
const upKey = Direction[0];     // upKey 的值是 "Up"
const downKey = Direction[1];   // downKey 的值是 "Down"
const leftKey = Direction[2];   // leftKey 的值是 "Left"
const rightKey = Direction[3];  // rightKey 的值是 "Right"

console.log(upKey);      // 输出: "Up"
console.log(downKey);    // 输出: "Down"

反向映射是数字枚举在编译时通过生成一个双向引用的 JavaScript 对象来实现的。字符串枚举和常量枚举由于其设计目标和编译产物的不同,不具备此特性。

6.使用场景

栗子1:定义状态码或错误码

这是枚举最经典的应用场景。当你的应用程序有固定的几种状态或错误类型时,使用枚举可以增强类型安全和代码可读性,避免使用硬编码。

enum PaymentStatus {
    Pending,
    Success,
    Failed,
    Refunded,
}

const handlePayment = (status: PaymentStatus) => {
    if (status === PaymentStatus.Success) {
        console.log('Payment successful');
    }
}
handlePayment(PaymentStatus.Success)//输出 Payment successful

栗子2:表示固定的选项集

当你有固定的选项列表,比如用户角色、权限级别或者 UI 主题时,枚举是一个很好的选择。

enum UserRole {
  Admin = "ADMIN",
  Editor = "EDITOR",
  Guest = "GUEST"
}

const checkPermission = (role: UserRole)=> {
  if (role === UserRole.Admin) {
    // ... 执行管理员操作
  }
}

栗子3:作为函数参数使用

在函数签名中使用枚举类型,可以明确地告诉调用者该参数应该传入什么类型的值,从而防止传入无效的 "魔术数字" 或字符串。

enum SortOrder {
    Asc,
    Desc,
}

const sortItems = (items: string[], order: SortOrder) => {
    if (order === SortOrder.Asc) {
        //升序
    } else {
        //降序
    }
}

栗子4:在 switch 语句中使用

枚举与 switch 语句是天作之合,可以让代码分支清晰明了。

enum OrderStatus {
    Pending,
    Processing,
    Shipped,
    Delivered,
    Cancelled
}

const getOrderStatusMessage = (status: OrderStatus): string => {
    switch (status) {
        case OrderStatus.Pending:
            return "订单待处理";
        case OrderStatus.Processing:
            return "订单处理中";
        case OrderStatus.Shipped:
            return "订单已发货";
        case OrderStatus.Delivered:
            return "订单已送达";
        case OrderStatus.Cancelled:
            return "订单已取消";
        default:
            // 通过 exhaustive check 确保所有情况都被处理
            const _exhaustiveCheck: never = status;
            return _exhaustiveCheck;
    }
}

参考文章

小满zs 学习TypeScript10(枚举类型)xiaoman.blog.csdn.net/article/det…