使用 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;
};

适用场景

  • 需要获取原始枚举值类型
  • 使用原始枚举值类型再去定义其他类型
相关推荐
子兮曰4 小时前
async/await高级模式:async迭代器、错误边界与并发控制
前端·javascript·github
恋猫de小郭4 小时前
2026 Flutter VS React Native ,同时在 AI 时代 VS Native 开发,你没见过的版本
android·前端·flutter
GIS之路6 小时前
ArcGIS Pro 中的 Notebooks 入门
前端
IT_陈寒8 小时前
React状态管理终极对决:Redux vs Context API谁更胜一筹?
前端·人工智能·后端
Kagol9 小时前
TinyVue 支持 Skills 啦!现在你可以让 AI 使用 TinyVue 组件搭建项目
前端·agent·ai编程
柳杉9 小时前
从零打造 AI 全球趋势监测大屏
前端·javascript·aigc
simple_lau9 小时前
Cursor配置MasterGo MCP:一键读取设计稿生成高还原度前端代码
前端·javascript·vue.js
睡不着先生9 小时前
如何设计一个真正可扩展的表单生成器?
前端·javascript·vue.js
天蓝色的鱼鱼9 小时前
模块化与组件化:90%的前端开发者都没搞懂的本质区别
前端·架构·代码规范
明君879979 小时前
Flutter 如何给图片添加多行文字水印
前端·flutter