TypeScript如何按枚举定义顺序而非字母序对对象数组排序
字符串枚举按定义顺序排序的实现方案
现有问题根源
TypeScript的字符串枚举编译为JavaScript后,仅会保留「枚举键-枚举字符串值」的映射关系,不会内置成员的定义顺序属性。当前使用sortBy直接返回对象的code字符串值作为排序键时,排序逻辑会默认按字符串的字典ASCII序做比较,因此会出现FIXTERM_1M排在FIXTERM_2W前面的异常顺序,和业务要求的枚举定义顺序不一致。
具体实现步骤
1. 建立枚举排序权重映射
排序的核心逻辑是给每个枚举值分配一个对应定义顺序的数字权重,数字越小越靠前。
有两种映射生成方式可选:
- 手动维护映射(适合枚举成员基本固定的场景):直接按照代码里定义
MyEnum的先后顺序,为每个枚举值分配连续的索引值:const ENUM_SORT_ORDER: Record<MyEnum, number> = { [MyEnum.FIXTERM1W]: 0, [MyEnum.FIXTERM2W]: 1, [MyEnum.FIXTERM1M]: 2, [MyEnum.FIXTERM2M]: 3, [MyEnum.FIXTERM3M]: 4, [MyEnum.FIXTERM6M]: 5, [MyEnum.FIXTERM1Y]: 6, [MyEnum.FIXTERMDEFAULT]: 7, [MyEnum.FIXTERMWA]: 8, [MyEnum.ONCALL24H]: 9, [MyEnum.ONCALL48H]: 10, [MyEnum.ONCALLWA]: 11 }; - 动态生成映射(适合枚举后续会新增成员的场景):利用JavaScript非整数索引的字符串键对象按插入顺序遍历的特性,直接从编译后的枚举对象中提取顺序,无需手动维护:
该方式生成的映射顺序和枚举的定义顺序完全一致,后续新增、调整枚举成员顺序时,映射会自动同步,不需要额外维护。const ENUM_SORT_ORDER: Record<string, number> = Object.values(MyEnum) .reduce((acc, cur, index) => ({ ...acc, [cur]: index }), {});
2. 替换原有排序逻辑
把原来排序函数里返回o.code的逻辑,替换为返回映射表中对应的权重值,同时增加兜底逻辑:万一遇到不在映射表中的枚举值,统一分配最大权重值,排到数组末尾,避免排序报错。
修改后的xxx getter代码如下:
get xxx(): Yyyy { if (this._myvalue && this._myvalue.myobject && this._myvalue.myobject.length > 0) { this._myvalue.myobject = sortBy(this._myvalue.myobject, (o: myobject) => ENUM_SORT_ORDER[o.code] ?? Number.MAX_SAFE_INTEGER ); } return this._myvalue; }
效果说明
调整后的排序逻辑会完全按照枚举的定义顺序排列数组元素,最终得到的序列就是业务期望的FIXTERM_1W → FIXTERM_2W → FIXTERM_1M → FIXTERM_2M ...的顺序,不会再出现按字符串字典序乱排的问题。
内容的提问来源于stack exchange,提问作者Haifisch
相关产品推荐
相关产品推荐

