稀土掘金技术社区 05月10日 09:47
enum-plus:前端福利!介绍一个天花板级的前端枚举库
index_new5.html
../../../zaker_core/zaker_tpl_static/wap/tpl_guoji1.html

 

Enum-Plus是一个增强版的枚举类库,完全兼容原生enum,并在此基础上进行了功能扩展。它支持多种数据类型,如number和string,并允许自定义显示文本,实现枚举项的国际化。通过简单的配置,Enum-Plus可以将枚举绑定到主流UI库,如Ant Design、ElementPlus等,快速生成下拉框等组件。此外,它还提供了丰富的API,如获取枚举项数组、根据值获取显示文本、判断枚举项是否存在等。Enum-Plus以零依赖、轻量级的特点,适用于各种前端框架和Node.js环境,是原生enum的理想替代品。

✨Enum-Plus完全兼容原生enum的用法,支持number、string等多种数据类型,并允许开发者自定义显示文本,使得枚举的语义更加清晰。

🌍Enum-Plus内置本地化能力,枚举项文本可实现国际化,可以与任何 i18n 库集成,方便开发者构建多语言应用。

🎨Enum-Plus支持将枚举绑定到Ant Design、ElementPlus、Material-UI等UI库,只需一行代码即可将枚举转换为下拉框等常用组件,极大地提升了开发效率。

🛠️Enum-Plus提供了丰富的API,例如items可以获取包含全部枚举项的只读数组,label可以根据枚举值或Key获取显示文本,toFilter可以生成表格列筛选,方便开发者进行各种操作。

💪Enum-Plus还提供了valueType类型约束,可以将数据类型从宽泛的number或string类型缩小为有限的枚举值序列,这不但能减少错误赋值的可能性,还能提高代码的可读性

原创 作业逆流成河 2025-05-10 09:04 重庆

(金石计划倒计时Ⅱ天,2篇原创推荐好文即可瓜分现金💴)简介enum-plus是一个增强版的枚举类库,完全兼容

(金石计划倒计时Ⅱ天,2篇原创推荐好文即可瓜分现金💴)

简介

enum-plus是一个增强版的枚举类库,完全兼容原生enum的基本用法,同时支持扩展显示文本、绑定到 UI 组件以及提供丰富的扩展方法,是原生enum的一个直接替代品。它是一个轻量级、零依赖、100% TypeScript 实现的工具,适用于多种前端框架,并支持本地化。

枚举项列表可以用来一键生成下拉框、复选框等组件,可以轻松遍历枚举项数组,获取某个枚举值的显示文本,判断某个值是否存在等。支持本地化,可以根据当前语言环境返回对应的文本,轻松满足国际化的需求。

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

特性

    完全兼容原生 enum 的用法
    支持numberstring等多种数据类型
    增强的枚举项,支持自定义显示文本
    内置本地化能力,枚举项文本可实现国际化,可与任何 i18n 库集成
    支持枚举值转换为显示文本,代码更简洁
    可扩展设计,允许在枚举项上添加自定义字段
    支持将枚举绑定到 Ant Design[1]ElementPlus[2]Material-UI[3] 等 UI 库,一行代码枚举变下拉框
    支持 Node.js 环境,支持服务端渲染 (SSR)
    零依赖,纯原生 JavaScript,可用于任何前端框架
    100% TypeScript 实现,具有全面的类型推断能力
    轻量 (gzip 压缩后仅 2KB+)

安装

    npm install enum-plus

    枚举定义

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

    1. 基础格式,与原生枚举用法基本一致

      import { Enum } from 'enum-plus';
      const Week Enum({  Sunday0,  Monday1,as const);
      Week.Monday; // 1

      as const 类型断言用于将枚举值变成字面量类型,类型更精确,否则它们将被作为number类型。如果你使用的是 JavaScript,请删除as const

      2. 标准格式(推荐)

      为每个枚举项指定 value (枚举值) 和 label(显示文本)字段,这是最常用的格式,也是推荐的格式。这种格式允许你为每个枚举项设置显示文本,这些文本可以在 UI 组件中使用

        import { Enum } from 'enum-plus';
        const Week Enum({  Sunday: { value0, label'星期日' },  Monday: { value1, label'星期一' },as const);
        Week.Sunday; // 0Week.label(0); // 星期日

        3. 数组格式

        数组格式在需要动态创建枚举时很有用,例如从 API 获取数据中动态创建一个枚举。这种方式还允许自定义字段映射,这增加了灵活性,可以适配不同的数据格式

          import { Enum } from 'enum-plus';
          const petTypes = await getPetsData();// [   { value: 1, key: 'dog', label: '狗' },//     { value: 2, key: 'cat', label: '猫' },//     { value: 3, key: 'rabbit', label: '兔子' }   ];const PetTypes = Enum(petTypes);

          4. 原生枚举格式

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

            import { Enum } from 'enum-plus';
            enum init {  Sunday = 0,  Monday,  Tuesday,  Wednesday,  Thursday,  Friday,  Saturday,}const Week = Enum(init);
            Week.Sunday; // 0Week.Monday; // 1Week.Saturday; // 6Week.label('Sunday'); // Sunday

            API

            💎拾取枚举值

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

              Week.Sunday// 0Week.Monday// 1

              💎items

              获取一个包含全部枚举项的只读数组,可以方便地遍历枚举项。由于符合 Ant Design[5] 组件的数据规范,因此支持将枚举一键转换成下拉框、复选框等组件,只需要一行代码!

              💎keys

              获取一个包含全部枚举项Key的只读数组

              💎label

              根据某个枚举值或枚举 Key,获取该枚举项的显示文本。如果设置了本地化,则会返回本地化后的文本。

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

                💎key

                根据枚举值获取该枚举项的 Key,如果不存在则返回undefined

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

                  💎has

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

                    Week.has(1); // trueWeek.has('Sunday'); // trueWeek.has(9); // falseWeek.has('Birthday'); // false

                    💎toSelect

                    toSelectitems相似,都是返回一个包含全部枚举项的数组。区别是,toSelect返回的元素只包含labelvalue两个字段,同时,toSelect方法支持在数组头部插入一个可自定义的默认元素,一般用于下拉框等组件的默认选项

                    💎toMenu

                    生成一个对象数组,可以绑定给 Ant Design[6] 的MenuDropdown等组件

                      import { Menu } from 'antd';
                      <Menu items={Week.toMenu()} />;

                      数据数据格式为:

                        [  { key0label'星期日' },  { key1label'星期一' },];

                        💎toFilter

                        生成一个对象数组,可以直接传递给 Ant Design[7] Table 组件的列配置,在表头中显示一个下拉筛选框,用来过滤表格数据

                        数据数据格式为:

                          [  { text'星期日'value0 },  { text'星期一'value1 },];

                          💎toValueMap

                          生成一个符合 Ant Design Pro[8] 规范的枚举集合对象,可以传递给 ProFormFieldProTable 等组件。

                          数据格式为:

                            {  0: { text: '星期日' },  1: { text: '星期一' },}

                            💎raw

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

                            第一个重载方法,返回枚举集合的初始化对象,即用来初始化 Enum 原始 init 对象。

                            第二个重载方法,用来处理单个枚举项,根据获取单个枚举项的原始初始化对象。

                            这个方法主要作用是,用来获取枚举项的自定义字段,支持无限扩展字段

                              const Week Enum({  Sunday: { value0, label'星期日', happytrue },  Monday: { value1, label'星期一', happyfalse },as const);
                              Week.raw(0).happy // trueWeek.raw(0); // { value: 0, label: '星期日', happy: true }Week.raw('Monday'); // { value: 1, label: '星期一', happy: false }Week.raw(); // { Sunday: { value: 0, label: '星期日', happy: true }, Monday: { value: 1, label: '星期一', happy: false } }

                              ⚡️valueType_「TypeScript ONLY」_

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

                                type WeekValues = typeof Week.valueType// 0 | 1
                                const weekValuetypeof Week.valueType = 1// ✅ 类型正确,1 是一个有效的周枚举值const weeks: (typeof Week.valueType)[] = [01]; // ✅ 类型正确,0 和 1 是有效的周枚举值const badWeekValuetypeof Week.valueType = 8// ❌ 类型错误,8 不是一个有效的周枚举值const badWeeks: (typeof Week.valueType)[] = [08]; // ❌ 类型错误,8 不是一个有效的周枚举值

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

                                用法

                                • 基本用法,与原生枚举用法一致

                                  const Week Enum({  Sunday: { value0, label'星期日' },  Monday: { value1, label'星期一' },as const);
                                  Week.Sunday; // 0Week.Monday; // 1

                                  • 支持为枚举项添加 Jsdoc 注释,代码提示更友好

                                  在代码编辑器中,将光标悬停在枚举项上,即可显示关于该枚举项的详细 Jsdoc 注释,而不必再转到枚举定义处查看

                                    const Week Enum({  /** 星期日 */  Sunday: { value0, label'星期日' },  /** 星期一 */  Monday: { value1, label'星期一' },as const);
                                    Week.Monday; // 将光标悬浮在 Monday 上

                                    可以看到,不但提示了枚举项的释义,还有枚举项的值,无需跳转离开当前光标位置,在阅读代码时非常方便

                                    • 获取包含全部枚举项的数组

                                      Week.items; // 输出如下:// [//  { value: 0, label: '星期日', key: 'Sunday', raw: { value: 0, label: '星期日' } },//  { value: 1, label: '星期一', key: 'Monday', raw: { value: 1, label: '星期一' } }// ]

                                      • 获取第一个枚举值

                                        Week.items[0].value; // 0

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

                                          Week.has(1); // trueWeek.items.some(item => item.value === 1); // true1 instanceof Week// true

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

                                            Week.items.length// 2Week.items.map((item) => item.value); // [0, 1],✅ 可遍历Week.items.forEach((item) => {}); // ✅ 可遍历for (const item of Week.items) {  // ✅ 可遍历}Week.items.push({ value2label'星期二' }); // ❌ 不可修改Week.items.splice(01); // ❌ 不可修改Week.items[0].label = 'foo'// ❌ 不可修改

                                            • 枚举值 (或 Key) 转换为显示文本

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

                                              • 枚举值转换为 Key

                                                Week.key(1); // 'Monday'Week.key(Week.Monday); // 'Monday'Week.key(9); // undefined, 不存在此枚举项

                                                • 添加扩展字段,不限数量

                                                  const Week Enum({  Sunday: { value0, label'星期日', activetrue, disabledfalse },  Monday: { value1, label'星期一', activefalse, disabledtrue },as const);
                                                  Week.raw(0).active // trueWeek.raw(Week.Sunday).active // trueWeek.raw('Sunday').active // true

                                                  🔥   转换成 UI 组件

                                                    生成 Select 下拉框

                                                      Ant Design | Arco Design Select
                                                    import { Select } from 'antd';
                                                    <Select options={Week.items} />;
                                                      Material-UI Select
                                                      import { MenuItemSelect } from '@mui/material';
                                                      <Select>  {Week.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={Week.items} textField="label" dataItemKey="value" />;
                                                          ElementPlus Select
                                                          <el-select>  <el-option v-for="item in Week.items" v-bind="item" /></el-select>
                                                            Ant Design Vue | Arc Design Select
                                                            <a-select :options="Week.items" />
                                                              Vuetify Select
                                                              <v-select :items="Week.items" item-title="label" />
                                                                Angular Material Select
                                                                <mat-select>  <mat-option *ngFor="let item of Week.items" [value]="item.value">{{ item.label }}</mat-option></mat-select>
                                                                  NG-ZORRO Select
                                                                  <nz-select>   <nz-option *ngFor="let item of Week.items" [nzValue]="item.value">{{ item.label }}</nz-option></nz-select>
                                                                    生成下拉菜单

                                                                  toMenu方法可以为 Ant Design[19]MenuDropdown 等组件生成数据源,格式为:{ key: number|string, label: string } []

                                                                    import { Menu } from 'antd';
                                                                    <Menu items={Week.toMenu()} />;
                                                                      生成表格列筛选

                                                                    toFilter方法可以生成一个对象数组,为表格绑定列筛选功能,列头中显示一个下拉筛选框,用来过滤表格数据。对象结构遵循 Ant Design[20] 的数据规范,格式为:{ text: string, value: number|string } []

                                                                      import { Table } from 'antd';
                                                                      const columns = [  {    title'week',    dataIndex'week',    filtersWeek.toFilter(),  },];// 在表头中显示下拉筛选项<Table columns={columns} />;
                                                                        支持 Ant Design Pro 组件生成

                                                                      toValueMap方法可以为 Ant Design Pro[21] 的ProFormFieldsProTable等组件生成数据源,这是一个类似 Map 的数据结构,格式为:{ [key: number|string]: { text: string } }

                                                                        import { ProFormSelectProFormCheckboxProFormRadioProFormTreeSelectProTable } from '@ant-design/pro-components';
                                                                        <ProFormSelect valueEnum={Week.toValueMap()} />// 下拉框<ProFormCheckbox valueEnum={Week.toValueMap()} />// 复选框<ProFormRadio.Group valueEnum={Week.toValueMap()} />// 单选框<ProFormTreeSelect valueEnum={Week.toValueMap()} />// 树选择<ProTable columns={[{ dataIndex: 'week', valueEnum: Week.toValueMap() }]} />// ProTable

                                                                        • 枚举合并(或者扩展枚举)

                                                                          const myWeek Enum({  ...Week.raw(),  Friday: { value5, label'星期五' },  Saturday: { value6, label'星期六' },});

                                                                          • 使用枚举值序列来缩小 number 取值范围   [TypeScript ONLY]

                                                                          使用 valueType 类型约束,可以将数据类型从宽泛的numberstring类型缩小为有限的枚举值序列,这不但能减少错误赋值的可能性,还能提高代码的可读性

                                                                            const weekValuenumber = 8// 👎 任意数字都可以赋值给周枚举,即使错误的const weekNamestring = 'Birthday'// 👎 任意字符串都可以赋值给周枚举,即使错误的
                                                                            const goodWeekValuetypeof Week.valueType = 1// ✅ 类型正确,1 是一个有效的枚举值const goodWeekNametypeof Week.keyType = 'Monday'// ✅ 类型正确,'Monday' 是一个有效的枚举名
                                                                            const badWeekValuetypeof Week.valueType = 8// ❌ 类型报错,8 不是一个有效的枚举值const badWeekNametypeof Week.keyType = 'Birthday'// ❌ 类型报错,'Birthday' 不是一个有效的枚举值
                                                                            type FooProps = {  value?: typeof Week.valueType// 👍 组件属性类型约束,可以防止错误赋值,还能智能提示取值范围  names?: (typeof Week.keyType)[]; // 👍 组件属性类型约束,可以防止错误赋值,还能智能提示取值范围};

                                                                            本地化

                                                                            enum-plus 本身不内置国际化能力,但支持通过 localize 可选参数传入一个自定义方法,来实现本地化文本的转化。这是一个非常灵活的方案,这使你能够实现自定义的本地化函数,根据当前的语言环境将枚举的 label 值转换为适当的翻译文本。语言状态管理仍由您自己负责,您的 localize 方法决定返回哪种本地化文本。对于生产环境的应用程序,我们强烈建议使用成熟的国际化库(如 i18next),而不是创建自定义解决方案。

                                                                            以下是一个简单的示例,仅供参考。请注意,第一种方法由于缺乏灵活性,不建议在生产环境中使用,它仅用于演示基本概念。请考虑使用第二种及后面的示例。

                                                                              import { Enum } from 'enum-plus';import i18next from 'i18next';import Localize from './Localize';
                                                                              let lang = 'zh-CN';const setLang = (l: string) => {  lang = l;};
                                                                              // 👎 这不是一个好例子,仅供演示,不建议生产环境使用const sillyLocalize = (content: string) => {  if (lang === 'zh-CN') {    switch (content) {      case 'enum-plus.options.all':        return '全部';      case 'week.sunday':        return '星期日';      case 'week.monday':        return '星期一';      default:        return content;    }  } else {    switch (content) {      case 'enum-plus.options.all':        return 'All';      case 'week.sunday':        return 'Sunday';      case 'week.monday':        return 'Monday';      default:        return content;    }  }};// 👍 建议使用 i18next 或其他国际化库const i18nLocalize = (content: string | undefined) => i18next.t(content);// 👍 或者封装成一个基础组件const componentLocalize = (content: string | undefined) => <Localize value={content} />;
                                                                              const Week = Enum(  {    Sunday: { value0label'week.sunday' },    Monday: { value1label'week.monday' },  } as const,  {    localize: sillyLocalize,    // localize: i18nLocalize, // 👍 推荐使用i18类库    // localize: componentLocalize, // 👍 推荐使用组件形式  });setLang('zh-CN');Week.label(1); // 星期一setLang('en-US');Week.label(1); // Monday

                                                                              当然,每个枚举类型都这样设置可能比较繁琐,enum-plus 提供了一种全局设置方案,可以通过 Enum.localize 全局方法,来全局设置本地化。如果两者同时存在,单个枚举的设置会覆盖全局设置。

                                                                                Enum.localize = i18nLocalize;

                                                                                全局扩展

                                                                                虽然 Enum 提供了一套全面的内置方法,但如果这些还不能满足你的需求,你可以使用 Enum.extends API 扩展其功能,添加自定义方法。这些扩展会全局应用于所有枚举实例,包括在扩展应用之前创建的实例,并且会立即生效,无需任何其它设置。

                                                                                  Enum.extends({  toMySelect(this: ReturnType<typeof Enum>) {    return this.items.map((item) => ({ value: item.valuetitle: item.label }));  },  reversedItems(this: ReturnType<typeof Enum>) {    return this.items.reverse();  },});
                                                                                  Week.toMySelect(); // [{ value: 0, title: '星期日' }, { value: 1, title: '星期一' }]

                                                                                  兼容性

                                                                                  enum-plus 提供了完善的兼容性支持。

                                                                                    「浏览器环境」

                                                                                      core-js
                                                                                      配置适当的 @babel/preset-env 和 useBuiltIns 设置
                                                                                      其他替代的 polyfill 实现

                                                                                      「现代打包工具」:对于支持 exports[22] 字段的打包工具(如 Webpack 5+、Vite、Rollup),enum-plus 的目标是 ES2020。如果需要更广泛的浏览器支持,可以在构建过程中使用 @babel/preset-env 转译为更早期的语法。

                                                                                      「旧版打包工具」:对于不支持 exports 字段的工具(如 Webpack 4),enum-plus 会自动回退到 main 字段的入口点,其目标是 ES2016

                                                                                      「Polyfill 策略」:为了最小化包的体积,enum-plus 不包含任何 polyfill。如果需要支持旧版浏览器,可以引入以下内容:

                                                                                    「Node.js 兼容性」:enum-plus 需要至少 ES2016 的特性,兼容 Node.js v7.x 及以上版本。

                                                                                  意犹未尽,还期待更多?不妨移步 Github 官网[23],你可以发现更多的高级使用技巧。

                                                                                  相信我,一定会让你感觉相见恨晚!

                                                                                  如果你喜欢这个项目,欢迎在 GitHub 上给项目点个 Star⭐ —— 这是程序员表达喜爱的通用语言😜~ 可以让更多开发者发现它!


                                                                                  关注更多AI编程资讯请去AI Coding专区:https://juejin.cn/aicoding

                                                                                  ""~

                                                                                  阅读原文

                                                                                  跳转微信打开

                                                                                  Fish AI Reader

                                                                                  Fish AI Reader

                                                                                  AI辅助创作,多种专业模板,深度分析,高质量内容生成。从观点提取到深度思考,FishAI为您提供全方位的创作支持。新版本引入自定义参数,让您的创作更加个性化和精准。

                                                                                  FishAI

                                                                                  FishAI

                                                                                  鱼阅,AI 时代的下一个智能信息助手,助你摆脱信息焦虑

                                                                                  联系邮箱 441953276@qq.com

                                                                                  相关标签

                                                                                  Enum-Plus 枚举 TypeScript 前端开发 UI组件
                                                                                  相关文章