使用 ts-enum-next 优雅的管理 typeScript enum

npm 包地址: www.npmjs.com/package/ts-...

在业务中,我们可能需要同时定义枚举值和枚举值说明,前者用来匹配,后者用来展示。

在 typescript 中可以使用 枚举 + 映射对象的方式实现。

ts 复制代码
enum Status {
    PENDING = 0,
    APPROVED = 1,
    REJECTED = 2
}

const StatusDescriptions = {
    [Status.PENDING]: "等待处理",
    [Status.APPROVED]: "已批准",
    [Status.REJECTED]: "已拒绝"
};

// 使用示例
console.log(Status.PENDING); // 0
console.log(StatusDescriptions[Status.PENDING]); // "等待处理"

或者使用对象字面量模拟枚举

ts 复制代码
const Status = {
    PENDING: {
        value: 0,
        description: "等待处理"
    },
    APPROVED: {
        value: 1,
        description: "已批准"
    },
    REJECTED: {
        value: 2,
        description: "已拒绝"
    }
} as const;

// 使用示例
console.log(Status.PENDING.value); // 0
console.log(Status.PENDING.description); // "等待处理"

在业务中,我们除了需要这样简单的枚举定义类型, 我们还会需要处理很多数据字典的业务场景。尤其是在以 Node 构建的服务端, 可能需要使用类的能力来定义这些枚举值, 以方便包含其他字段、方法、构造函数、描述元数据等能力。

ts-enum-next 根据在 Java 中使用 enum 的场景,封装了一个抽象类 Enum 和一些辅助的工具类型, 来提供类似 Java 的枚举功能:

  • Java 形式的数据定义
  • 丰富的枚举元数据
  • 双向查找能力
  • 枚举集合操作
  • 自定义行为支持

ts-enum-next 的使用场景

场景1: 基础枚举定义(带值和描述)

定义枚举时, 同时添加: 枚举值、枚举名称、枚举描述元数据(可选)

ts 复制代码
import { Enum } from 'ts-enum-next';

class HttpStatus extends Enum<number> {
    static readonly OK = new HttpStatus(200, "OK", "请求成功");
    static readonly BAD_REQUEST = new HttpStatus(400, "BAD_REQUEST", "错误请求");
    static readonly NOT_FOUND = new HttpStatus(404, "NOT_FOUND", "资源未找到");
}


// 使用示例
console.log(HttpStatus.OK.value); // 200
console.log(HttpStatus.OK.name); // "OK"
console.log(HttpStatus.OK.description); // "请求成功"

适用场景

  • 需要为枚举值附加元信息(如状态码描述)
  • 需要根据数值快速查找对应的枚举实例
  • 需要保持严格的类型安全

场景2: 枚举集合操作

ts 复制代码
// 获取所有枚举实例, 返回的是所有的枚举类
console.log(HttpStatus.values());  // [HttpStatus, HttpStatus, HttpStatus, ....]



 // 通过值获取枚举实例
 console.log(HttpStatus.fromValue(200));  // HttpStatus(200, "OK", "请求成功")
 
 // 通过名称获取枚举实例
  console.log(HttpStatus.fromName('OK'));  // HttpStatus(200, "OK", "请求成功")
  
  
  
 // 创建枚举集合
const errorStatus = HttpStatus.setOf(
       HttpStatus.BAD_REQUEST,  
       HttpStatus.NOT_FOUND
);

console.log(errorStatus); // Set(2) {HttpStatus, HttpStatus}


// 检查包含关系
const currentStatus = HttpStatus.fromValue(400)

if (errorStatus.has(currentStatus))) {
    console.error("当前是错误状态:", currentStatus.description);
}

适用场景

  • 需要分组管理枚举值(如所有错误状态)
  • 需要检查枚举值是否属于某个特定集合
  • 需要遍历枚举的所有可能值

场景 3:枚举映射表

csharp 复制代码
// 创建枚举到字符串的映射
const statusMessages = HttpStatus.enumMap<string>({
    [HttpStatus.OK]: "操作成功完成",
    [HttpStatus.BAD_REQUEST]: "请检查您的请求参数",
    [HttpStatus.NOT_FOUND]: "请求的资源不存在"
});

// 使用映射
console.log(statusMessages.get(HttpStatus.NOT_FOUND)); // "请求的资源不存在"

适用场景

  • 需要为不同枚举值关联不同的数据
  • 需要高效查找枚举对应的资源
  • 需要类型安全的键值存储

场景 4:自定义枚举方法

ts 复制代码
class OrderStatus extends Enum<number> {
    static readonly CREATED = new OrderStatus(0, "CREATED");
    static readonly PAID = new OrderStatus(1, "PAID");
    static readonly SHIPPED = new OrderStatus(2, "SHIPPED");
    
    private constructor(
        public readonly value: number,
        public readonly name: string
    ) {
        super();
    }
    
    // 自定义方法
    public canTransitionTo(target: OrderStatus): boolean {
        const validTransitions = {
            [OrderStatus.CREATED.value]: [OrderStatus.PAID.value],
            [OrderStatus.PAID.value]: [OrderStatus.SHIPPED.value]
        };
        return validTransitions[this.value]?.includes(target.value) || false;
    }
}

// 使用自定义方法
const current = OrderStatus.CREATED;
console.log(current.canTransitionTo(OrderStatus.PAID)); // true
console.log(current.canTransitionTo(OrderStatus.SHIPPED)); // false

适用场景

  • 需要为枚举添加业务逻辑
  • 需要实现状态机或工作流
  • 需要封装枚举相关的复杂判断逻辑

场景 5:枚举序列化/反序列化

ts 复制代码
class UserRole extends Enum<string> {
    static readonly ADMIN = new UserRole("admin", "Administrator");
    static readonly EDITOR = new UserRole("editor", "Content Editor");
    static readonly VIEWER = new UserRole("viewer", "Read-only User");
    
    private constructor(
        public readonly value: string,
        public readonly displayName: string
    ) {
        super();
    }
    
    // JSON序列化
    public toJSON() {
        return this.value;
    }
    
    // 从JSON反序列化
    public static fromJSON(value: string): UserRole {
        return UserRole.fromValue(value);
    }
}

// 序列化示例
const role = UserRole.ADMIN;
const json = JSON.stringify(role); // ""admin""

// 反序列化示例
const parsedRole = UserRole.fromJSON(JSON.parse(json));
console.log(parsedRole === UserRole.ADMIN); // true

适用场景

  • 需要将枚举与JSON相互转换
  • 需要处理API响应中的枚举值
  • 需要保持前后端枚举值的一致性

场景 6:获取原始枚举值类型

ts 复制代码
import { Enum, EnumValues } from 'ts-enum-next';

class HttpStatus extends Enum<200 | 400 | 404> {
    static readonly OK = new HttpStatus(200, "OK", "请求成功");
    static readonly BAD_REQUEST = new HttpStatus(400, "BAD_REQUEST", "错误请求");
    static readonly NOT_FOUND = new HttpStatus(404, "NOT_FOUND", "资源未找到");
}

// 获取HttpStatus 的原始枚举值类型
export type HttpStatusEnum = EnumValues<typeof HttpStatus>;

// 使用原始枚举值类型再去定义其他类型
export type ResponseData<T> = {
	message: string;
	data: T;
	code: HttpStatusEnum;
};

适用场景

  • 需要获取原始枚举值类型
  • 使用原始枚举值类型再去定义其他类型
相关推荐
CodeCraft Studio18 分钟前
数据透视表控件DHTMLX Pivot v2.1发布,新增HTML 模板、增强样式等多个功能
前端·javascript·ui·甘特图
一把年纪学编程20 分钟前
【牛马技巧】word统计每一段的字数接近“字数统计”
前端·数据库·word
llc的足迹29 分钟前
el-menu 折叠后小箭头不会消失
前端·javascript·vue.js
九月TTS1 小时前
TTS-Web-Vue系列:移动端侧边栏与响应式布局深度优化
前端·javascript·vue.js
Johnstons1 小时前
AnaTraf:深度解析网络性能分析(NPM)
前端·网络·安全·web安全·npm·网络流量监控·网络流量分析
whatever who cares1 小时前
CSS3 伪元素(Pseudo-elements)大全
前端·css·css3
若愚67922 小时前
前端取经路——性能优化:唐僧的九道心经
前端·性能优化
Bl_a_ck2 小时前
开发环境(Development Environment)
开发语言·前端·javascript·typescript·ecmascript
田本初3 小时前
使用vite重构vue-cli的vue3项目
前端·vue.js·重构
ai产品老杨3 小时前
AI赋能安全生产,推进数智化转型的智慧油站开源了。
前端·javascript·vue.js·人工智能·ecmascript