Important: This documentation covers Yarn 1 (Classic).
For Yarn 2+ docs and migration guide, see yarnpkg.com.

Package detail

enum-plus

shijistar19.7kMIT3.1.1TypeScript support: included

A drop-in replacement for native enum. Like native enum but much better!

enum, enumeration, javascript, typescript, front-end, back-end, node.js, browser, mini-program, react-native, ui-binding, ssr, localization, globalization, plugin-system, react, vue, angular

readme

English | 中文 | CHANGELOG

enum-plus

像原生 enum 一样,但更强大!


npm latest version npm package minimized gzipped size npm downloads Ask DeepWiki code coverage GitHub License

支持平台

Node compatibility Web Browsers React Native MiniProgram Taro

⬇️  简介 | 特性 | 安装 | 枚举定义 | API | 静态方法 | 全局配置 | 使用案例 | 插件系统 | 本地化 | 全局扩展 | 命名冲突 | 最佳实践| 兼容性 | 常见问题 | 支持  ⬇️

🎉 v3.0 发布了!

新版本是一个重大的里程碑版本,带来了很多令人兴奋的功能和改进,详情请参考 发布说明迁移指南

如果升级后,你遇到枚举类型都变成 any 的问题,请看这里

简介

enum-plus 是一个增强版的枚举类库,完全兼容原生enum的用法,是原生枚举的直接替代品。支持为枚举项添加显示名称,以及添加自定义元数据字段。可以用枚举直接生成下拉框、多选框、菜单、选项卡等各种 UI 控件,对前端工程师非常实用。

为枚举增加了很多扩展方法,支持对枚举项数组的遍历和各种数据转换。你可以把数值转换为多种语言的枚举名称,因为它支持国际化,这在 UI 回显业务数据时非常有用。

这是一个轻量级、零依赖、100% TypeScript 实现的工具库,适用于任何前端框架,包括无框架的纯原生应用。

还有哪些令人兴奋的特性呢?请继续探索吧!或者不妨先看下这个使用视频。

usage video

<summary>这里有几个常见问题,有兴趣也可以阅读一下</summary>

特性

  • 完全兼容原生 enum 的用法
  • 支持numberstring等多种数据类型
  • 枚举项支持设置显示名称
  • 支持国际化,可与任何 i18n 库集成
  • 快速将值转换为显示名称,在 UI 回显时非常有用
  • 枚举项支持扩展元数据字段,可以作为静态配置系统使用
  • 支持插件体系,可以通过安装插件扩展枚举功能
  • 支持数据类型约束,提高代码的类型安全性  TypeScript
  • 枚举可以生成下拉框等 UI 组件,支持 Ant DesignElement PlusMaterial-UI 等多种组件库
  • 支持 Web浏览器、Node.js、React Native、Taro、小程序等多种环境
  • 支持服务端渲染 (SSR)
  • 兼容任何前端开发框架,支持无框架的纯原生项目
  • 面向 TypeScript 设计,具有良好的类型推导和代码补全能力
  • 零依赖项
  • 轻量(gzip压缩后仅2KB+)

安装

使用 npm 安装:

npm install enum-plus

使用 pnpm 安装:

pnpm add enum-plus

使用 bun 安装:

bun add enum-plus

或者使用 yarn:

yarn add enum-plus

浏览器中运行:

  • 特定版本号:
<!-- 兼容 ES2020 的现代版本 -->
<script src="https://cdn.jsdelivr.net/npm/enum-plus@v3.1.1/umd/enum-plus.min.js"></script>
<!-- 兼容 ES2015 的早期版本 -->
<script src="https://cdn.jsdelivr.net/npm/enum-plus@v3.1.1/umd/enum-plus-legacy.min.js"></script>
  • 最新版本:
<!-- 兼容 ES2020 的现代版本 -->
<script src="https://cdn.jsdelivr.net/npm/enum-plus/umd/enum-plus.min.js"></script>
<!-- 兼容 ES2015 的早期版本 -->
<script src="https://cdn.jsdelivr.net/npm/enum-plus/umd/enum-plus-legacy.min.js"></script>

⬇️ 下载文件:

你也可以从 GitHub 发布 下载这些文件

枚举定义

本节展示了使用 Enum 函数初始化枚举的多种方式,你可以根据不同的使用场景选择最合适的方法

1. Key-Value 格式

import { Enum } from 'enum-plus';

// Number 类型
const WeekEnum = Enum({
  Sunday: 0,
  Monday: 1,
});

WeekEnum.Monday; // 1

// String 类型
const WeekEnum2 = Enum({
  Sunday: 'Sun',
  Monday: 'Mon',
});

WeekEnum2.Monday; // 'Mon'

如果你的项目使用 TypeScript 且版本低于 5.0,那么建议你为 Enum 方法的参数添加 as const 类型断言,这样枚举值将保持原始的字面量值,而不会变成numberstring类型。关于更多详情,请参考 这里

2. 标准格式(推荐)

为每个枚举项指定 value (枚举值) 和 label(显示名称)字段,这是最常用的格式,也是推荐的格式。这种格式允许你为每个枚举项设置显示名称,这些文本可以在 UI 组件中使用。关于为 label 字段启用本地化支持,请参考本地化章节

import { Enum } from 'enum-plus';

const WeekEnum = Enum({
  Sunday: { value: 0, label: '星期日' },
  Monday: { value: 1, label: '星期一' },
});

WeekEnum.Sunday; // 0
WeekEnum.items[0].key; // 'Sunday'
WeekEnum.items[0].label; // 星期日

想要输入 label 时启用代码智能提示?请参考 启用枚举项标签的智能提示 章节,了解更多详情。

3. Key-Label 格式

只提供 keylabel 字段创建枚举。如果省略了 value 字段,则它默认为与 key 字段相同。

import { Enum } from 'enum-plus';

const WeekEnum = Enum({
  Sunday: { label: '星期日' },
  Monday: { label: '星期一' },
});

WeekEnum.Sunday; // 'Sunday'
WeekEnum.items[0].key; // 'Sunday'
WeekEnum.items[0].label; // 星期日

4. 数组格式

数组格式在需要动态创建枚举时很有用,例如从 API 获取数据中动态创建一个枚举。

你可以动态映射字段以适应各种不同的数据结构。请参考 数组格式初始化,设置不同的字段映射 章节,了解更多详情。

import { Enum } from 'enum-plus';

const pets = [
  { value: 1, key: 'Dog', label: '狗' },
  { value: 2, key: 'Cat', label: '猫' },
  { value: 3, key: 'Rabbit', label: '兔' },
];
const PetEnum = Enum(pets);

PetEnum.Dog; // 1
PetEnum.label(1); // 狗

5. 原生枚举格式

如果你已经有一个原生的枚举,你可以直接传递给Enum函数,它会自动转换为增强版的枚举,这样可以借用原生枚举的枚举值自动递增特性

import { Enum } from 'enum-plus';

enum WeekNative {
  Sunday = 0,
  Monday,
  Tuesday,
  Wednesday,
  Thursday,
  Friday,
  Saturday,
}
const WeekEnum = Enum(WeekNative);

WeekEnum.Sunday; // 0
WeekEnum.Monday; // 1
WeekEnum.Saturday; // 6

枚举还支持一些配置项,以更好地控制枚举的行为,详情请参考 枚举配置选项 章节。

API

💎   拾取枚举值

Enum.XXX

像原生enum一样,直接拾取一个枚举值

WeekEnum.Sunday; // 0
WeekEnum.Monday; // 1

💎   named

Record<string, EnumItemClass>

一个聚合了所有枚举项的只读对象,可以通过key来快速访问某个枚举项对象。

WeekEnum.named.Monday; // { key: 'Monday', value: 1, label: '星期一' }

💎   items

{ value, label, key, raw }[]

获取一个包含全部枚举项的只读数组,可以方便地遍历枚举项。

WeekEnum.items; // [ { value: 0, label: '星期日', key: 'Sunday' }, { value: 1, label: '星期一', key: 'Monday' }, ... ]

💎   values

(string | number)[]

获取一个包含全部枚举项value的数组

WeekEnum.values; // [0, 1, 2, 3, 4, 5, 6]

💎   labels

string[]

获取一个包含全部枚举项label的数组

WeekEnum.labels; // ['星期日', '星期一', ... '星期五', '星期六']

💎   keys

string[]

获取一个包含全部枚举项key的数组

WeekEnum.keys; // ['Sunday', 'Monday', ... 'Friday', 'Saturday']

💎   meta

Record<string, any[]>

获取一个包含全部枚举项自定义字段的聚合对象,键是字段名,值是该字段的所有枚举项值的数组,这样可以在不遍历枚举项的情况下访问自定义字段。

const ColorEnum = Enum({
  Red: { value: 1, label: '红色', hex: '#FF0000' },
  Green: { value: 2, label: '绿色', hex: '#00FF00' },
  Blue: { value: 3, label: '蓝色', hex: '#0000FF' },
});
ColorEnum.meta.hex; // ['#FF0000', '#00FF00', '#0000FF']

顺便一提,可以通过 namedraw 属性快速访问单个枚举项的自定义字段

ColorEnum.named.Red.raw.hex; // '#FF0000'

💎   has

[方法]   has(keyOrValue?: string | number): boolean

判断某个枚举项(值或 key)是否存在

WeekEnum.has(1); // true
WeekEnum.has('Sunday'); // true
WeekEnum.has(9); // false
WeekEnum.has('Birthday'); // false

💎   findBy

[方法]   findBy(field: string, value: any): EnumItemClass | undefined

根据指定字段和字段值,获取枚举项对象,如果不存在则返回undefined

字段名支持:keyvaluelabel或元数据字段

ColorEnum.findBy('value', 1); // { key: 'Red', value: 1, label: '红色', hex: '#FF0000' }
ColorEnum.findBy('key', 'Red'); // { key: 'Red', value: 1, label: '红色', hex: '#FF0000' }
ColorEnum.findBy('hex', '#FF0000'); // { key: 'Red', value: 1, label: '红色', hex: '#FF0000' }

💎   label

[方法]   label(keyOrValue?: string | number): string | undefined

根据某个枚举值或枚举 key,获取该枚举项的显示名称。如果启用了本地化,则会返回当前语言的内容。

WeekEnum.label(1); // 星期一
WeekEnum.label('Monday'); // 星期一

💎   key

[方法]   key(value?: string | number): string | undefined

根据枚举值获取该枚举项的key,这也被称为反向映射。如果不存在则返回undefined

WeekEnum.key(1); // 'Monday'

💎   raw

[方法^1]   raw(): Record<K, T[K]>
[方法^2]   raw(keyOrValue: V | K): T[K]

raw方法有两种重载形式。第一种是返回整个枚举集合的原始初始化对象,即Enum方法的第一个参数。

第二种是返回单个枚举项的原始初始化对象,即Enum方法的第一个参数中对应字段的子对象。

这个方法主要作用是,用来获取枚举项的自定义字段。

const WeekEnum = Enum({
  Sunday: { value: 0, label: '星期日', happy: true },
  Monday: { value: 1, label: '星期一', happy: false },
});

WeekEnum.raw(0).happy; // true
WeekEnum.raw(0); // { value: 0, label: '星期日', happy: true }
WeekEnum.raw('Monday'); // { value: 1, label: '星期一', happy: false }
WeekEnum.raw(); // { Sunday: { value: 0, label: '星期日', happy: true }, Monday: { value: 1, label: '星期一', happy: false } }

温馨提示:如果要获取某个已知枚举项的元数据字段,使用enum.named.XXX.raw 是一个不错的选择。


💎   toList

[方法^1]   toList(): { value, label }[]
[方法^2]   toList(options?: { valueField?: string; labelField?: string }): { [key: string]: any }[]

将枚举转换为一个默认包含valuelabel字段的数组,或者通过options参数自定义字段名。

WeekEnum.toList();
// [
//   { value: 0, label: '星期日' },
//   { value: 1, label: '星期一' },
//   ...
//   { value: 6, label: '星期六' }
// ]
WeekEnum.toList({ valueField: 'id', labelField: 'name' });
// [
//   { id: 0, name: '星期日' },
//   { id: 1, name: '星期一' },
//   ...
//   { id: 6, name: '星期六' }
// ]

💎   toMap

[方法^1]   toMap(): Record<string, string | number>
[方法^2]   toMap(options?: { keySelector?: string; valueSelector?: string }): Record<string, any>

将枚举转换为一个默认以value为键,label为值的对象,或者通过options参数自定义键和值的字段名。

WeekEnum.toMap();
// {
//   "0": '星期日',
//   "1": '星期一',
//   ...
//   "6": '星期六'
// }
WeekEnum.toMap({ keySelector: 'key', valueSelector: 'value' });
// {
//   "Sunday": 0,
//   "Monday": 1,
//   ...
//   "Saturday": 6
// }

💎   name

string

整个枚举集合的显示名称。可以在创建枚举时,通过传入一个可选的 name 参数来为枚举类型命名。这个名称可以是一个普通字符串,也可以是一个本地化键值,以支持国际化文本。请参考本地化章节,了解更多详情。

const WeekEnum = Enum(
  {
    Sunday: { value: 0, label: '星期日' },
    Monday: { value: 1, label: '星期一' },
  },
  {
    name: 'i18n.enums.week', // 可以普通字符串或者一个本地化键值
  }
);

WeekEnum.name; // Week 或 周,取决于当前语言

在 UI 组件中,枚举通常用来作为数据源,生成下拉框表单项,或在表格单元格中显示枚举成员文本。而对应的表单项标签或列标题就是枚举类型的名称。通过使用name,我们可以集中管理枚举名称,和枚举成员的名称,也更方便使用。


⚡️   valueType     [TypeScript Only]

value1 | value2 | ...

在 TypeScript 中,提供了一个包含所有枚举值的联合类型,用于缩小变量或组件属性的数据类型。这种类型替代了像 numberstring 这样宽泛的原始类型,使用精确的值集合,防止无效赋值,同时提高代码可读性和编译时类型安全性。

const weekValue: typeof WeekEnum.valueType = 1;

function setToday(day: typeof WeekEnum.valueType) {
  // ...
}

const MyComponent = (props: { day: typeof WeekEnum.valueType }) => {
  // ...
};

注意,这只是一个 TypeScript 类型,只能用来约束类型。不可在运行时调用,运行时调用会抛出异常。


⚡️   keyType     [TypeScript Only]

key1 | key2 | ...

valueType类似,获取一个包含全部枚举 key 的联合类型

type WeekKeys = typeof WeekEnum.keyType; // 'Sunday' | 'Monday'
const weekKey: typeof WeekEnum.keyType = 'Monday';
const weekKeys: (typeof WeekEnum.keyType)[] = ['Sunday', 'Monday'];

注意,这只是一个 TypeScript 类型,只能用来约束类型。不可在运行时调用,运行时调用会抛出异常。


⚡️   rawType     [TypeScript Only]

{ value: V, label: string, [...] }

获取初始化整个枚举集合的原始类型,即 Enum 函数的第一个参数的类型。

不要与 raw 方法混淆,raw 方法是一个运行时方法,而rawType是一个 TypeScript 的类型。

type WeekRaw = typeof WeekEnum.rawType;
// { Sunday: { value: 0, label: string }, Monday: { value: 1, label: string } }

注意,这只是一个 TypeScript 类型,只能用来约束类型。不可在运行时调用,运行时调用会抛出异常。


静态方法

💎   Enum.isEnum

[方法]   isEnum(obj: any): boolean

判断一个对象是否是一个由Enum函数创建的枚举对象

Enum.isEnum(WeekEnum); // true
Enum.isEnum({}); // false

💎   Enum.localize

[方法]   (key: string) => string

设置全局的本地化函数,用来处理枚举类型名称和枚举项显示名称的本地化。请参考 本地化 章节,了解更多详情。

import i18n from 'i18next';

Enum.localize = (key) => i18n.t(key);

💎   Enum.extends

[方法]   (obj: Record<string, Function>) => void

为所有枚举对象添加全局扩展方法,请参考全局扩展章节,了解更多详情。

Enum.extends({
  sayHello() {
    return `你好,EnumPlus!`;
  },
});

💎   Enum.install

[方法]   (plugin: Plugin, options?: any) => void

安装一个插件,插件可以为所有枚举添加新的功能。请参考插件系统章节,了解更多详情。

import i18nextPlugin from '@enum-plus/plugin-i18next';

Enum.install(i18nextPlugin);

全局配置

Enum.config 提供了一些全局配置参数,用来影响枚举的行为和特性。

autoLabel

Enum.config.autoLabel 是一个全局配置选项,用于自动生成枚举项的标签。它允许在定义枚举时,设置 options.labelPrefix 选项,为所有枚举项设置一个 label 前缀,枚举项只需要设置基础值即可,甚至可以省略 label 字段(与 key 字段相同)。这样可以减少重复代码,提高枚举定义的简洁性。

Enum.config.autoLabel 的值可以是一个布尔值,也可以使用 function 类型的函数以实现更复杂的逻辑。

  • true - 默认值,启用自动标签生成功能。枚举项的 label 最终值将自动设置为 labelPrefix+label,如果省略了 label 字段,则使用 labelPrefix+key 规则。当然,如果创建枚举时没有设置 labelPrefix,则此选项将没有任何效果。
  • function - 一个自定义函数,用于自定义每个枚举项 label 生成规则。该函数接受一个选项对象参数,其中包含:item(枚举项对象)和 labelPrefix,并返回一个字符串作为最终的 label 值。

    Enum.config.autoLabel = ({ item, labelPrefix }) => {
      return `${labelPrefix}.${item.key.lowerFirst()}`;
    };
  • false - 禁用自动标签生成功能,枚举项必须显式提供 label 字段。

请注意,在创建枚举时也可以通过 options.autoLabel 参数覆盖全局配置,其用法与 Enum.config.autoLabel 相同。

使用案例

💡 基础用法,消除魔法数字

const WeekEnum = Enum({
  Sunday: { value: 0, label: '星期日' },
  Monday: { value: 1, label: '星期一' },
});

if (today === WeekEnum.Sunday) {
  // 今天是星期天,享受你的一天吧!
} else if (today === WeekEnum.Monday) {
  // 哦不,又是星期一了...
}

💡 检查是否一个有效的枚举值

if (WeekEnum.has(value)) {
  // 是一个有效的枚举值,可以安全使用
} else {
  // 抛出异常或使用默认值
}

💡 检查是否一个枚举对象

let values: number[] | undefined;
if (Enum.isEnum(data)) {
  values = data.values;
} else if (Array.isArray(data)) {
  values = data;
} else {
  // 非法输入,抛出异常或使用默认值
}

💡 生成 UI 组件

以 React + Ant Design 为例,更多 UI 组件的案例请参考 支持多种前端框架 章节

import { Menu, Select, Table } from 'antd';
import { ProFormCheckbox, ProFormSelect } from '@ant-design/pro-components';

const App = () => {
  return (
    <>
      <Select options={WeekEnum.items} />
      <Menu items={WeekEnum.toMenu()} />
      <Table columns={[{ filters: WeekEnum.toFilter() }]} />
      <ProFormSelect valueEnum={WeekEnum.toValueMap()} />
      <ProFormCheckbox valueEnum={WeekEnum.toValueMap()} />
    </>
  );
};

需要安装 @enum-plus/plugin-antd 插件


💡 枚举名称/标签支持国际化

可以支持多语言环境,将label字段设置为一个本地化键值,根据当前语言环境显示对应的文本。请参考 本地化 章节,了解更多详情。

WeekEnum.label(1); // Monday 或 星期一,取决于当前语言环境
WeekEnum.named.Monday.label; // Monday 或 星期一,取决于当前语言环境
WeekEnum.name; // Week 或 周,取决于当前语言环境

💡 约束数据类型 (仅 TypeScript)

这是一个 TypeScript 特有的特性,可以使用 valueType 约束变量、方法参数或组件属性的类型,防止无效赋值,提高代码的类型安全性。

  • 变量
type WeekValues = typeof WeekEnum.valueType; // 0 | 1 | ... | 5 | 6

const weekValue: WeekValues = 1; // ✅ 正确,1 是一个有效的周枚举值
const weeks: WeekValues[] = [0, 1]; // ✅ 正确,0 和 1 是有效的周枚举值

const badWeekValue1: WeekValues = 'Weekend'; // ❌ 类型错误,"Weekend" 不是数字
const badWeekValue2: WeekValues = 8; // ❌ 错误,8 不是一个有效的周枚举值
const badWeeks: WeekValues[] = [0, 8]; // ❌ 错误,8 不是一个有效的周枚举值
  • 方法参数
function setDay(day: typeof WeekEnum.valueType) {
  // day 的类型被约束为 0 | 1 | ... | 5 | 6
}

setDay(1); // ✅ 正确
setDay('Monday'); // ❌ 类型错误,'Monday' 不是数字
setDay(8); // ❌ 错误,8 不是一个有效的枚举值
  • 组件属性
type MyComponentProps = {
  day: typeof WeekEnum.valueType; // 0 | 1 | ... | 5 | 6
};
const MyComponent = (props: MyComponentProps) => {
  return <div>今天是 {WeekEnum.label(props.day)}</div>;
};

<MyComponent day={1} />; // ✅ 类型正确
<MyComponent day="Monday" />; // ❌ 类型错误
<MyComponent day={8} />; // ❌ 错误,8 不是一个有效的枚举值

💡 添加元数据字段,可以作为静态配置系统使用

const ColorEnum = Enum({
  Red: { value: 1, hex: '#FF0000', icon: '🔥' },
  Green: { value: 2, hex: '#00FF00', icon: '🍏' },
  Blue: { value: 3, hex: '#0000FF', icon: '🔵' },
});

ColorEnum.values; // [1, 2, 3]
ColorEnum.keys; // ['Red', 'Green', 'Blue']
ColorEnum.meta.hex; // ['#FF0000', '#00FF00', '#0000FF']
ColorEnum.meta.icon; // ['🔥', '🍏', '🔵']
ColorEnum.named.Red.raw.hex; // '#FF0000'
ColorEnum.named.Red.raw.icon; // '🔥'

💡 支持遍历枚举项数组,但不可修改

Array.isArray(WeekEnum.items); // true
WeekEnum.items.map((item) => item.value); // [0, 1, ..., 5, 6]
WeekEnum.items.forEach((item) => {
  // ✅ 可遍历
});
for (const item of WeekEnum.items) {
  // ✅ 可遍历
}

WeekEnum.items.push({ value: 2, label: '星期二' }); // ❌ 不可修改
WeekEnum.items.splice(0, 1); // ❌ 不可修改
WeekEnum.items[0].label = 'foo'; // ❌ 不可修改

💡 枚举组合(合并)

const PrimaryColorEnum = Enum({
  Red: { value: 1, hex: '#FF0000' },
  Green: { value: 2, hex: '#00FF00' },
  Blue: { value: 3, hex: '#0000FF' },
});
const SecondaryColorEnum = Enum({
  Yellow: { value: 4, hex: '#FFFF00' },
  Cyan: { value: 5, hex: '#00FFFF' },
  Magenta: { value: 6, hex: '#FF00FF' },
});
const AllColorEnum = Enum({
  ...PrimaryColorEnum.raw(),
  ...SecondaryColorEnum.raw(),
});

💡 启用枚举项标签的智能提示

如果你启用了国际化,你可能想在输入枚举项标签时能够获得代码智能提示,列出所有可用的国际化资源的键值列表,简化输入过程。你可以通过为 EnumLocaleExtends 接口添加一个新的属性来实现这一点。

index.ts

declare module 'enum-plus/extension' {
  type EN = typeof import('./packages/locals/en').default;
  interface EnumLocaleExtends {
    LocaleKeys: keyof EN;
  }
}

💡 枚举项支持 JSDoc 注释,启用代码智能提示

在代码编辑器中,将光标悬停在枚举项上,即可显示关于该枚举项的详细 JSDoc 注释,而不必再转到枚举定义处查看。关于如何编写良好的代码,请参考 最佳实践 章节。

const WeekEnum = Enum({
  /** 星期日 */
  Sunday: { value: 0, label: '星期日' },
  /** 星期一 */
  Monday: { value: 1, label: '星期一' },
});

WeekEnum.Monday; // 将光标悬浮在 Monday 上

JSDoc

可以看到,当光标悬浮在枚举项上时,可以同时显示枚举值和枚举项的介绍。无需跳转离开当前光标位置,去查看枚举的定义,这在阅读代码时非常方便。


💡 支持多种前端框架

Enum.items 可以直接作为组件的数据源(以 Select 组件为例)

  • React相关框架

    Ant Design | Arco Design Select

    import { Select } from 'antd';
    
    <Select options={WeekEnum.items} />;

    Material-UI Select

    import { MenuItem, Select } from '@mui/material';
    
    <Select>
      {WeekEnum.items.map((item) => (
        <MenuItem key={item.value} value={item.value}>
          {item.label}
        </MenuItem>
      ))}
    </Select>;

    Kendo UI Select

    import { DropDownList } from '@progress/kendo-react-dropdowns';
    
    <DropDownList data={WeekEnum.items} textField="label" dataItemKey="value" />;
  • Vue相关框架

    Element Plus Select

    <el-select>
      <el-option v-for="item in WeekEnum.items" v-bind="item" />
    </el-select>

    Ant Design Vue | Arco Design Select

    <a-select :options="WeekEnum.items" />

    Vuetify Select

    <v-select :items="WeekEnum.items" item-title="label" />
  • Angular相关框架

    Angular Material Select

    <mat-select>
      @for (item of WeekEnum.items; track item.value) {
      <mat-option [value]="item.value">{{ item.label }}</mat-option>
      }
    </mat-select>

    NG-ZORRO Select

    <nz-select>
      @for (item of WeekEnum.items; track item.value) {
        <nz-option [nzValue]="item.value">{{ item.label }}</nz-option>
      }
    </nz-select>

💡 枚举配置选项

在创建枚举时,可以传入一个可选的配置对象,用来定制枚举的行为和特性。下面是一些常用的配置选项:

interface EnumOptions {
  /** 枚举类型名称,可以是一个普通字符串,或者一个本地化键值 */
  name?: string;
  /** 为所有枚举项设置一个标签前缀,更多详情请参考 [全局配置] 章节 */
  labelPrefix?: string;
  /** 自动生成枚举项标签的规则,更多详情请参考 [全局配置] 章节 */
  autoLabel?: boolean | ((params: { item: EnumItemClass; labelPrefix?: string }) => string);
  /** 枚举实例级别的本地化函数,会覆盖 Enum.localize 全局配置函数 */
  localize?: (localeKey: string) => string;
}

更多配置选项,请参考下面一个章节。


💡 在数组初始化方式中,设置不同的字段映射

4. 数组格式 章节中,介绍了可以通过后端动态数据来构建枚举,但是很可能动态数据的字段名并不是valuelabelkey,而是其它的字段名。这时你可以传入一个自定义选项,把这些映射到其它字段名上

import { Enum } from 'enum-plus';

const data = await getPetsData();
// [   { id: 1, code: 'dog', name: '狗' },
//     { id: 2, code: 'cat', name: '猫' },
//     { id: 3, code: 'rabbit', name: '兔' }   ];
const PetTypeEnum = Enum(data, {
  getValue: 'id',
  getLabel: 'name',
  getKey: 'code', // getKey可选
});
PetTypeEnum.items; // 输出如下:
// [   { value: 1, label: '狗', key: 'dog' },
//     { value: 2, label: '猫', key: 'cat' },
//     { value: 3, label: '兔', key: 'rabbit' }   ]

在上面的例子中,getValuegetLabelgetKey 还可以是一个函数,用来处理更复杂的业务逻辑,比如:

const PetTypeEnum = Enum(petTypes, {
  getValue: (item) => item.id,
  getLabel: (item) => `${item.name} (${item.code})`,
  getKey: (item) => item.code,
});

插件系统

enum-plus 提供了一个插件系统,允许你为枚举添加额外的功能。插件可以为所有枚举实例添加新的方法或属性,极大地扩展了枚举的功能。你可以选择性地安装需要的插件,而不是将所有功能都打包在一起,从而保持核心库的轻量和高效。

import antdPlugin from '@enum-plus/plugin-antd';
import { Enum } from 'enum-plus';

Enum.install(antdPlugin);

当你安装一个插件后,插件会为所有枚举实例添加新的方法或属性。例如,安装了 @enum-plus/plugin-antd 插件后,你可以使用 enum.toSelect 方法使用枚举生成一个 Select 组件。

你还可以设置插件的可选配置选项,以定制插件的行为,关于插件的配置选项,请参考各个插件的文档。

import antdPlugin from '@enum-plus/plugin-antd';
import { Enum } from 'enum-plus';

Enum.install(antdPlugin, {
  toSelect: {
    valueField: 'id', // 设置 toSelect 方法生成的数据对象中,关于值的字段名
    labelField: 'name', // 设置 toSelect 方法生成的数据对象中,关于枚举名称的字段名
  },
});

插件生态

目前我们已经开发并发布了以下插件,你可以根据需要选择安装:

我们正在开发以下插件:

  • @enum-plus/plugin-angular: Angular 集成,包括支持 Enum.localize 返回 Angular 组件,以及监听语言变化以自动重新渲染组件。我们需要你的帮助来开发这个插件!

如果你没有找到需要的插件,或者你想开发自己的插件,请参阅 插件开发指南。你可以在enum-plus官方仓库中开发新插件,也可以将你开发的插件发布到 npm 上,并把你的插件链接分享在这里。我们真诚地需要你的帮助,来丰富插件生态系统!


本地化

enum-plus 默认不内置国际化能力,因此枚举项的label字段将被视为普通字符串,直接返回原始文本。

为 enum-plus 添加本地化支持,最简单的方式是安装对应的 i18n插件,例如 @enum-plus/plugin-i18next,它会自动将 labelname 字段的值传递给 i18next 进行翻译。

npm install @enum-plus/plugin-i18next i18next

然后在项目入口文件中安装插件:

index.js

import i18nextPlugin from '@enum-plus/plugin-i18next';
import { Enum } from 'enum-plus';

Enum.install(i18nextPlugin);

安装了插件后,枚举的 labelname 字段将自动通过 i18next 进行翻译。

const WeekEnum = Enum(
  {
    Sunday: { value: 0, label: 'week.sunday' },
    Monday: { value: 1, label: 'week.monday' },
  },
  { name: 'weekDays.name' }
);
WeekEnum.label(1); // Monday 或 星期一,取决于当前语言环境
WeekEnum.named.Monday.label; // Monday 或 星期一,取决于当前语言环境
WeekEnum.name; // Week 或 周,取决于当前语言环境

此插件还支持自定义 i18next 选项,甚至允许完全控制 localize 方法,请参考插件文档,了解更多详情。

如果你需要切换语言后自动更新UI,这需要借助 React、Vue 或 Angular 等框架的能力,请考虑使用 @enum-plus/plugin-react@enum-plus/plugin-vue 等插件。

如果你使用的是其它国际化库,例如 react-intlvue-i18nextngx-translate,你可以通过 Enum.localize 方法来集成这些库。

my-extension.js

import { Enum } from 'enum-plus';

Enum.localize = (key) => {
  // 这是一段伪代码,请根据你使用的国际化库进行调整
  return intl.formatMessage({ id: key });
};

一旦你完成了这项功能,建议你考虑把它发布成一个 npm 包,并分享在插件生态章节中,这样其他人也可以受益于你的工作。如果你觉得这个项目非常通用,也可以考虑把它提交到 enum-plus 官方插件库中,具体开发规则请参阅 插件开发指南


全局扩展

Enum 提供了丰富的内置方法和属性,它们已经可以满足大多数常见的使用场景。如果这些还不够,你还可以使用 Enum.extends 扩展更多的自定义方法。这些扩展会全局应用于所有枚举实例,包括在扩展应用之前创建的实例,并且会立即生效,无需任何额外的设置。

实际上,整个插件系统以及 Enum.install 在底层都是通过 Enum.extends 来实现的。

  • TypeScript 项目

    my-enum-extension.ts

    // 功能实现
    Enum.extends({
      toMySelect() {
        return this.items.map((item) => ({ value: item.value, title: item.label }));
      },
      reversedItems() {
        return this.items.toReversed();
      },
    });
    
    // 类型声明,以获得更好的类型提示
    declare module 'enum-plus/extension' {
      export interface EnumExtension<T, K, V> {
        toMySelect: () => { value: V; title: string }[];
        reversedItems: () => EnumItemClass<EnumItemInit<V>, K, V>[];
      }
    }

    index.ts

    然后在项目的入口文件中导入这个文件:

    import './my-enum-extension';
    
    WeekEnum.toMySelect(); // [{ value: 0, title: '星期日' }, { value: 1, title: '星期一' }]
  • JavaScript 项目

    my-enum-extension.js

    import { Enum } from 'enum-plus';
    
    Enum.extends({
      toMySelect() {
        return this.items.map((item) => ({ value: item.value, title: item.label }));
      },
      reversedItems() {
        return this.items.toReversed();
      },
    });

    my-enum-extension.js.d.ts

    import { EnumExtension, EnumItemClass, EnumItemInit } from 'enum-plus';
    
    declare module 'enum-plus/extension' {
      export interface EnumExtension<T, K, V> {
        toMySelect: () => { value: V; title: string }[];
        reversedItems: () => EnumItemClass<EnumItemInit<V>, K, V>[];
      }
    }

    index.js

    然后在项目的入口文件中导入这个文件:

    import './my-enum-extension';
    
    WeekEnum.toMySelect(); // [{ value: 0, title: '星期日' }, { value: 1, title: '星期一' }]

注意,EnumExtension 是一个泛型接口,它接受三个类型参数,它们的含义分别是:

  • T: 表示枚举类型的初始化对象
  • K: 表示枚举项的键值
  • V: 表示枚举项的值

如果你希望在扩展方法中提供更友好的类型提示,你可能需要使用到这些类型参数。当然,这些类型参数是可选的,如果你不需要,可以直接忽略掉它们。


命名冲突?

enum-plus 设计时充分考虑了命名冲突的可能性。枚举项的命名空间与枚举实例的方法和属性是分开的,这样可以最大限度地减少冲突的可能性。例如,当枚举项的名称与某个方法名称相同时,你可以通过 items 属性访问那些被覆盖的方法。

import { KEYS, VALUES } from 'enum-plus';

const WeekEnum = Enum({
  foo: { value: 1 },
  bar: { value: 2 },
  keys: { value: 3 }, // 命名冲突
  values: { value: 4 }, // 命名冲突
  label: { value: 5 }, // 命名冲突
  named: { value: 6 }, // 命名冲突
  toList: { value: 7 }, // 命名冲突
});

WeekEnum.foo; // 1
WeekEnum.bar; // 2
// 以下均为枚举项,优先级更高,会覆盖掉原来的方法
WeekEnum.keys; // 3
WeekEnum.values; // 4
WeekEnum.label; // 5
WeekEnum.named; // 6
WeekEnum.toList; // 7

// 可以 .items 访问到这些被覆盖的方法 🙂
WeekEnum.items[KEYS]; // ['foo', 'bar', 'keys', 'values', 'label', 'named', 'toList']
WeekEnum.items[VALUES]; // [1, 2, 3, 4, 5, 6, 7]
WeekEnum.items.label(1); // 'foo'
WeekEnum.items.named.foo; // { value: 1, label: 'foo', key: 'foo' }
WeekEnum.items.toList(); // [{ value: 1, label: 'foo' }, ...]

请注意,keysvalues 这两个属性比较特殊,因为它们是 JavaScript 数组的内置方法,为了避免改变 items 数组的行为,需要使用 KEYSVALUES 两个符号作为别名来访问它们。

再极端一点,万一 items 与枚举项命名冲突怎么办?放心,你仍然可以通过 ITEMS 别名来访问它。

import { ITEMS } from 'enum-plus';

const WeekEnum = Enum({
  foo: { value: 1 },
  bar: { value: 2 },
  items: { value: 3 }, // 命名冲突
  toList: { value: 4 }, // 命名冲突
});

WeekEnum.items; // 3,枚举项优先级更高,会覆盖掉 items
WeekEnum[ITEMS].toList(); // 但可以通过 ITEMS 别名来访问它

最佳实践

在使用 enum-plus 创建和管理枚举时,遵循一些最佳实践可以帮助你编写更清晰、可维护的代码。以下是一些建议:

  1. 枚举类型命名: 采用 PascalCase 大驼峰命名法,并以 Enum 作为后缀,如 WeekEnumColorEnum 等。
  2. 枚举成员命名: 使用 PascalCase 大驼峰命名法,如 SundayRed 等。这种命名方式突显了枚举成员的静态与不可变性,并且在IDE智能提示中可以显示在顶部,而不是与其它方法名混在一起,更方便查看和拾取。
  3. 语义明确: 确保枚举和成员名称具有清晰的语义,良好的语义命名能够自解释代码意图,降低理解成本。
  4. 单一职责原则: 每个枚举类型应专注表达一组高内聚的相关常量,避免不同枚举类型之间的职责重叠。
  5. 提供JSDoc注释: 为每个枚举项添加 JSDoc 注释,说明其含义和用途。完善的JSDoc文档能在IDE中提供悬停提示,提升代码阅读体验。同样也建议为枚举类添加注释。
  6. 国际化架构: 建议从开始就搭建国际化架构,可集成本库提供的 本地化 机制。预先设计的国际化方案能够避免后期重构的高成本,并使应用更易于扩展到全球市场。

下面是一个示例,展示了如何结合上述最佳实践来定义一个枚举:

/** 表示一周的枚举 */
const WeekEnum = Enum(
  {
    /** 星期日 */
    Sunday: { value: 0, label: 'enums.week.sunday' },
    /** 星期一 */
    Monday: { value: 1, label: 'enums.week.monday' },
    // ...
    /** 星期五 */
    Friday: { value: 5, label: 'enums.week.friday' },
    /** 星期六 */
    Saturday: { value: 6, label: 'enums.week.saturday' },
  },
  { name: 'enums.week.name' }
);

兼容性

enum-plus 设计之初就考虑了广泛的兼容性需求,可无缝运行于各类环境,包括现代浏览器、Node.js 以及多种构建工具。下面详细说明各环境的兼容性情况:

浏览器环境

  • 现代打包工具:对于支持 exports 配置的打包工具(如 webpack 5+、vite、rollup),代码引入的是 es 目录,对应的 ECMAScript 版本是 ES2020

  • 旧版打包工具:对于不支持 exports 配置的旧版打包工具(如 webpack 4),代码引入的是 es-legacy 目录,对应的 ECMAScript 版本是 ES2015

  • UMD版本:为了方便在浏览器中直接使用,或者在没有打包工具的静态项目中使用,enum-plus 还提供了 UMD 版本,存放在 umd 目录下。UMD 格式的文件可以通过 <script> 标签直接引入,通过 window.EnumPlus 获取类库内容。umd 目录提供了两种版本:

    • enum-plus.min.js:对应的 ECMAScript 版本是 ES2020,适用于现代浏览器
    • enum-plus-legacy.min.js:对应的 ECMAScript 版本是 ES2015,适用于旧版浏览器
  • Polyfill 策略:为了最小化包的体积,除了 UMD 格式,enum-plus 不包含任何 polyfill。如果需要支持旧版浏览器,可以自行引入以下工具:

    • core-js
    • 使用 @babel/preset-env 并配置合适的 useBuiltIns 选项
    • 其他替代的 polyfill 实现

Node.js 环境

在 Node.js 环境下,支持通过 requireimport 语法引入 enum-plus。

  • require

    对于所有支持 CommonJS 的 Node.js 版本,均可通过 require('enum-plus') 方式引入 enum-plus。代码引入的是 lib 目录,对应的 ECMAScript 版本是 ES2015。Node.js版本最低可以向下兼容到 v7.x

  • import

    对于支持 ES Module 的 Node.js 现代版本(Node.js 14.13+),可以通过 import { Enum } from 'enum-plus' 方式引入 enum-plus。代码引入的是 es 目录,对应的 ECMAScript 版本是 ES2020


常见问题

为什么需要这个库?TypeScript 已经有内置的枚举了

TypeScript 的内置枚举类型(enum)只是实现了枚举的基本功能,即消除魔法数字和流程控制。但对于一个前端工程师来说,枚举的需求远不止于此。我们还需要:

  1. 消除魔法数字
  2. ifswitch 语句中进行流程控制
  3. 为枚举添加显示名称,并支持国际化
  4. 为枚举扩展元数据字段,例如颜色、图标、描述等
  5. 枚举直接生成各种表单控件,例如下拉框、菜单、选项卡等
  6. 把数字直接转换成对应的国际化枚举名称,回显业务数据变得很轻松

如果你需要这些功能,那么 enum-plus 就是为你量身打造的。如果你是一个前端工程师,强烈建议你尝试一下!

好像 TypeScript 要废弃 enum 了?

无论 enum 这个特性是否未来会被替代,但枚举这个概念不会消失,在很多高级语言中这是最基础的特性之一。

enum-plus 恰恰是为了弥补 TypeScript 内置 enum 的不足而诞生的。它是一个纯粹的运行时库,不会受到 TypeScript 语言发展的影响。所以,你完全可以放心使用它。它既不会过时,未来也不会被废弃。

TypeScript 官方并没有明确的计划废除 enum,但是确实在一些情况下可能会禁止使用 enum。根本原因还是 enum 既不是纯粹的TypeScript类型(在编译时可以被彻底移除),也不是纯粹的JavaScript运行时代码,而是两者的混合体,这给编译器带来了较大的复杂性。

枚举库的性能怎么样?

enum-plus 始终关注性能。它的设计目标之一就是在提供丰富功能的同时,保持高效的性能表现。

对于 WeekEnum.Monday 这种最基本的用法,性能表现与原生枚举是相同的,因为它们在底层都是直接访问JavaScript对象的成员字段。

对于枚举项数组的遍历或查找等操作,与原生数组的性能是一样的,因为枚举项集合的底层就是一个被冻结的原生数组。

由此可见,在性能方面几乎已经达到了极致,你完全可以放心使用它,而不必担心性能问题。

为什么不支持反向映射?

请使用 enum.key(value) 方法来获取枚举项的键名,这种反向映射的方式不但适用于数字类型的枚举值,也适用于字符串类型的枚举值。

为什么启用国际化后,Ant Design下拉框的搜索功能失效了?

这是因为 Enum.localize 返回了一个组件对象,而不是常规字符串,导致 antd 无法正确进行字符串匹配。请使用 enum.isMatch 方法来实现自定义搜索功能。请参考 @enum-plus/plugin-react,了解更多详情。

npm install @enum-plus/plugin-react
import { Select } from 'antd';

<Select options={WeekEnum.items} filterOption={WeekEnum.isMatch} />;

如果你使用的是 @enum-plus/plugin-i18next 插件,或者自己实现了 Enum.localize 方法并且返回的是字符串,那么下拉框的搜索功能应该可以正常工作。

我必须使用 TypeScript 吗?我的是 JavaScript 项目要怎么办?

不用担心,无论你的项目是 TypeScript 还是 JavaScript,enum-plus 都可以正常工作,并且两种项目都可以享受到类型安全和智能提示的好处。VSCode等现代代码编辑器已经内置了对 TypeScript 的支持,因此你并不需要在项目中安装 TypeScript 依赖。

TypeScript 版本必须升级到 5.0+ 吗?

不是的。升级 TypeScript 5.0 是为了得到更好的开发体验,如果你选择不升级,它仍然是可以正常工作的,只需要一小点额外的工作。

const WeekEnum = Enum({
  Sunday: 0,
  Monday: 1,
} as const);

可以看到,在较低版本的TypeScript中,你可能需要使用 as const 类型断言。as const 可以让枚举值保持原始的字面量值,而不会变成 numberstring 类型,同时 enum.valueType 类型也会保持 0 | 1,而不会变成 number 类型。这让 TypeScript 的类型校验变得更准确,也可以提升代码的安全性。关于如何升级TypeScript以及如何修改项目配置,请仔细阅读 迁移指南

如果你使用的是 JavaScript,那么你可以借助 JSDoc 来让编辑器精确识别类型。

/** @type {{ Sunday: 0; Monday: 1 }} */
const weekInit = { Sunday: 0, Monday: 1 };

const WeekEnum = Enum(weekInit);

为什么升级到 3.0 之后,所有枚举的类型都变成了 any?

这是因为 tsconfig.json 的配置不正确,请仔细阅读 迁移指南

我在发行公告里看到,你们让 Jest 和 Playwright 共享了同一套测试代码,这很有意思。能介绍一下如何实现的吗?

是的,这并不轻松。Jest 和 Playwright 的工作原理并不相同,Jest 运行在 Node.js 环境中,而 Playwright 运行在浏览器环境中。为了让它们共享一套测试代码,我们做了以下工作:

  1. 环境适配:我们为不同的测试框架编写了一个适配层,处理它们之间的差异。
  2. 抽象测试逻辑:我们将测试逻辑抽象出来,放在一些独立的模块中,这样就可以在不同的测试框架中复用这些测试套件。
  3. 增强的序列化机制:e2e测试要求在浏览器环境中运行,然后把运行结果传递到 Node.js 环境中,再执行断言。为此,我们开发了一个增强的序列化库。由于在 enum-plus 枚举的内部用到了 functionSymbolDateRegExp 类型,重写了 Symbol.toStringTagSymbol.hasInstance 内置函数,甚至包括 Getter/Setter 这些特性,这些都是 JSON.stringify 无法序列化的,我们通过 jsoneo 实现了对这些复杂特性的支持,从而可以让复杂对象经过 序列化/反序列化 跨越不同的环境,并且保留了所有的动态行为。传递后的对象仍然是的,就像原始的对象没有经过序列化过一样。

基于这些工作,我们成功地让 Jest 和 Playwright 共享了一套测试代码,大大提高了单元测试的开发效率,降低了维护成本,你不必维护两套测试代码。未来我们还会把 第1部分 独立成一个开源项目,如果你在开发一个 通用JavaScript(Universal JavaScript)项目,或许你也可以尝试这种方式来共享测试代码。

我有一个很好的点子,希望为这个项目做贡献,我要怎么做?

我非常欢迎你为这个项目做贡献!以下是一些指导原则,能帮助你决定如何贡献:

得益于 enum-plus 的 插件系统,我们要为 enum-plus 扩展新功能变得非常容易。你可以根据功能的通用性和依赖关系,选择以下三种方式之一来贡献:

  1. 核心库 - 新功能对所有人都适用,且不引入外部依赖。你可以直接贡献到核心库,请参考 CONTRIBUTING 指南。
  2. 官方插件库 - 新功能需要依赖某个 开放的 框架或类库,并且在这个框架或类库已经有很多人在使用了。你可以贡献到官方插件库,请参考 插件开发指南
  3. 自定义插件 - 新功能需要引入某个闭源的外部依赖,或者这个领域比较小众,建议你自己发布一个 npm 包,并把你的插件链接分享在 插件生态 章节中,同样可以共享给所有人。

安全性

如果你发现安全问题,请遵循 安全策略 来负责任地报告。

支持

如果你觉得这个项目有帮助,请考虑在 GitHub 上给它一个 星标⭐️。这有助于更多人发现这个项目,并鼓励我们继续开发。

changelog

enum-plus Changelog

3.1.1

2025-10-22

Features

  • ✨ Introduce meta-only mode in Enum creation, allowing the creation of Enums without value and label fields. This is useful for scenarios where only metadata is needed for enum items.
  • ✨ Implementation instanceof operator of Enum method, and add type guard to provide type narrowing functionality. This allows you to use instanceof to check if an object is an enum object created by Enum.
  • ✨ Add type guard to Enum.has method.
  • 🛠️ Allow the type extending for Enum.name, just like enum labels.
  • 📝 Add documentation for TypeScript 5.0 upgrade instructions

3.1.0

2025-10-21

Features

  • ✨ Introduce Enum.config to manage global configuration for all Enums.
    • Enum.config.autoLabel to enable/disable automatic label generation for enum items by specifying the label prefix.
  • ✨ Add options.labelPrefix to specify the label prefix for enum items during Enum creation.
  • ✨ Add options.autoLabel to enable/disable automatic label generation on Enum creation. It overrides the global configuration.
  • ✨ Allow extending EnumItemLabel type to support IntelliSense.

3.0.1

2025-10-6

Features

  • 🛠 Improve type guard feature of Enum.isEnum method.
  • 📝 Add the badge of DeepWiki in README.

3.0.0

2025-10-5

🎉 v3.0 is Arrived!

This is a milestone release that brings many exciting features and improvements. Enjoy the new version!

Please refer to the Release Notes and Migration Guide for details.

Features

  • ✨ Introduce the new Plugin System. Many fantastic features can be shared as plugins, and you can enhance Enum by installing them.
  • 💄 Simplified enum initialization. No as const assertion is required on TypeScript ≥ 5.0. Thanks to @otomad.
  • ✨ New enum.named for quick access EnumItem by key.
  • ✨ New enum.meta to aggregate custom metadata fields across items.
  • ✨ New enum.labels returning a readonly array of labels.
  • ✨ New enum.toList to transform enum items to a list of { value, label } objects. Supports remapping the field names via options.
  • ✨ New enum.toMap to transform enum items to a mapping object. Supports remapping the field names via options.
  • ✨ New Enum.isEnum for type guarding.
  • ✨ New enum.findBy to locate an item by built-in or metadata fields.
  • ✨ New Enum.install to install plugins.
  • 🛠️ Typing: instanceof narrowing for EnumCollection; updated Enum.extend typing; graceful downgrade across TS versions.
  • ✨ Ship UMD module format under umd folder for direct browser usage.

Notable Changes

  • The typing declaration of extending Enums has changed
  • Recommended to upgrade TypeScript to 5.0

Breaking Changes

  • The following deprecated methods are removed:
    • enums.values
    • enums.options
    • enums.menus
    • enums.filters
    • enums.valuesEnum
  • The following methods are removed from the core library and moved to the @enum-plus/plugin-antd plugin. Please install the plugin to use them.
    • enums.toSelect
    • enums.toMenu
    • enums.toFilter
    • enums.toValueMap
  • The following symbols are renamed:
    • ENUM_COLLECTION symbol is renamed to IS_ENUM.
    • ENUM_ITEM symbol is renamed to IS_ENUM_ITEM.
    • ENUM_ITEMS symbol is renamed to IS_ENUM_ITEMS.
    • EnumValuesArray interface is renamed to EnumItemsArray, and the ...rest parameter is removed.
    • IEnumValues interface is renamed to IEnumItems.

Bug Fixes

  • 🐞 Fix sourcemap resolution issues in CommonJS mode

2.4.3

2025-9-4

Security

  • 🔒 Bump sha.js from 2.4.11 to 2.4.12 to address security vulnerabilities.

2.4.2

2025-7-8

Bug Fixes

  • 🐞 Fix the issue where lib/extension.d.ts was missing, which caused all enum types to default to any.

2.4.1

⚠️ This version is deprecated. Please use v2.4.2 instead.

2025-7-7

Bug Fixes

  • 🐞 Fix lib/extension.d.ts missing issue, but failed. Please use v2.4.2 instead.

2.4.0

⚠️ This version has a critical issue, please use v2.4.2 instead.

2025-7-6

Features

  • 🛠 Support Node.js ESM
  • 🛠 Remove file circular dependencies

2.3.5

2025-7-6

Features

  • 🛠 Downgrade the requirement of TypeScript to v3.8

2.3.4

2025-7-2

Features

  • ✨ Enhance the type definitions for methods like Enum.label, Enum.key, and Enum.raw to ensure return types more accurately correspond to input values. When an input value can be matched within the enum, the return type will no longer include undefined.

2.3.3

2025-6-19

Features

  • 🔥 Allow naming Enum types, accept both plain text and localization keys, similar to the localization for enum members.
  • 🛠 Mark Enum collection fields as readonly.
  • 🛠 Improve the type of Enum.labelEnum.keyEnum.raw parameters, to accept the real value types.

2.3.2

2025-6-10

Features

  • ✨ Improve type IntelliSense for array initialization Enums, allowing enum items to be listed as literals. Thanks to @mudoo.

2.3.1

2025-6-7

Features

  • ✨ Add IEnum to packages exports

2.3.0

2025-5-23

Features

  • ✨ Export new symbols ENUM_ITEMENUM_ITEMS and ENUM_COLLECTION which are used to access some special internal properties.
  • ✨ Add [ENUM_COLLECTION]: true to the Enum class, which is used to indicates that this is as an enum collection.
  • ✨ Add [ENUM_ITEM]: true to the EnumItem class, which is used to indicates that this is as an enum item.
  • ✨ Add [ENUM_ITEMS]: true to Enum.items array, which is used to indicates that this is as an enum items array.

Notable Changes

  • 💣 Remove [Symbol.toStringTag]: "EnumItem" from EnumItem class. The result of Object.prototype.toString.call(enumItem) is changed from [object EnumItem] back to [object Object]. If you are relying on this, please use enumItem[ENUM_ITEM] === true instead.
  • 💣 Remove [Symbol.toStringTag]: "EnumCollection" from Enum class. The result of Object.prototype.toString.call(enum) is changed from [object EnumCollection] to [object Array]. If you are relying on this, please use enum[ENUM_COLLECTION] === true instead.

2.2.11

2025-5-15

Features

  • 🛠 Remove "type": "commonjs" from package.json, which may breaks webpack bundling.

2.2.10

2025-5-14

Features

  • ✨ Enhance the type inference of the raw method. When the input value matches a specific enum item, it only returns the raw object of that enum item instead of returning the raw objects of all enum items.

2.2.9

2025-4-20

Features

  • 🛠 Emit a warning while trying to modify an EnumItem

Bug Fixes

  • 🐞 the output lib directory structure is incorrect. This will break legacy Node.js applications using the CommonJS module spec, while modern Node.js applications using the NodeNext module spec remain unaffected. This issue was introduced in v2.2.7. For node.js applications, it's strongly recommended to upgrade.

2.2.8

2025-3-30

Bug Fixes

  • 🐞 Fix exports configuration for moduleResolution ESNext

2.2.7

2025-3-30

Features

  • 🛠 provide different versions of ESModule output for modern browsers and legacy browsers

2.2.6

2025-3-29

Features

  • 🛠 change compile transformer
  • 👀 support ES2020 and Chrome>=80, if you need to support legacy browsers, please use use a modern bundler like webpack or vite and use babel to include proper polyfills on-demand.
  • 👀 for the Node.js environment, backward compatible down to ES2016.
  • 🛠 generate better sourcemaps
  • 🛠 package size reduces by 0.1k

2.2.5

2025-3-7

Features

  • 🛠 improve Enum typing, support boolean and Date as enum values

2.2.4

2025-2-24

Features

  • 🛠 Support global type extension for enum localization keys, providing better editor intelligence awareness

2.2.3

2025-2-19

Features

  • 🛠 Enum.localize supports delayed assignment, i.e. sets the function after the enum is created

2.2.2

2025-2-10

Features

  • 🛠 Change the return type of Enum.options.getKey
  • 📖 Update docs

2.2.1

2025-2-10

  • 📖 Update docs

2.2.0

2025-2-9

Features

  • 🔥 Support initializing Enum with native enums
  • 🔥 Add items array, deprecated the values array. Reduces package size.

2.1.1

2025-2-8

Bug Fixes

  • 🐞 Fix typing error in EnumExtension interface

2.1.0

2025-2-8

Note: This version has a typing issue, please use v2.1.1

Features

  • 🔥 Add toSelect method, deprecated the options method
  • 🔥 Add toMenu method, deprecated the menus method
  • 🔥 Add toFilter method, deprecated the filters method
  • 🔥 Add toValueMap method, the valuesEnum method
  • 🔥 Support global extension, custom methods can be added to Enums

2.0.3

2025-2-6

Features

  • 🛠 Downgrade EcmaScript version to ES2015

2.0.2

2025-2-3

Features

  • 🔥 The firstOption of options method supports localization

2.0.1

2025-2-2

Features

  • 🔥 Support for enum text localization
    • the Enum method now accepts a localize option that can be used to localize the enum text
    • you can also set the Enum.localize static method to localize all enums in a lower priority
  • 🔥 Add menus method

Breaking Changes

  • 💣 All parameters after the first of the Enum method has been changed to an options object

1.0.3

2023-11-14

  • 🛠 Both the enum.raw or enumItem.raw methods return the original array item, if an enum is created from array,

1.0.2

2023-07-31

  • 🆕 Add rawType accessor

1.0.1

2023-03-09

  • 🆕 Add a new filters method that returns an array of enumerated items that can be passed directly to the Column.filters of the AntDesign Table component as a list of filtered items for the column

  • 1.0.0

2022-10-08

  • 🆕 The first release of enum-plus library