TypeScript中使用Object.values处理enum是否会保留定义顺序?
字符串枚举
Object.values返回顺序是否稳定? 结论
你当前的字符串枚举使用场景下,Object.values(Foo)的输出顺序完全可以稳定依赖,永远会按照你定义枚举成员的顺序返回['one', 'two', 'three']。
原因说明
- TypeScript的字符串枚举编译后是无反向映射的普通JavaScript对象,键就是枚举成员名,值为对应的字符串,键插入顺序和你定义枚举成员的顺序完全一致。
- 从ES2015开始,ECMAScript官方规范明确规定了对象键的遍历顺序规则:
- 优先提取所有可转为非负整数的键,按数值从小到大排列
- 剩余的字符串类型键,严格按照插入对象的先后顺序排列
- 最后是Symbol类型键,同样按插入顺序排列
你示例中的枚举键都是非数字的普通字符串,所以遍历顺序完全遵循插入顺序,Object.values返回结果的顺序是稳定可预期的。即使是需要兼容老旧的ES5运行环境也无需担心,非数字键按插入顺序遍历在ES2015规范落地前就已经是所有主流浏览器的事实标准,不存在兼容性问题。
注意避坑
如果使用的是数字枚举,不要直接用Object.values获取成员值:数字枚举会生成反向映射(比如enum Foo { One = 1 }编译后会同时存在One: 1和1: 'One'两个键),数字类型的键会被优先排序,最终返回的顺序会和定义顺序不一致。
如果需要兼容数字枚举的场景,可以使用下面的类型安全工具函数:
function getEnumValues<T extends object>(enumObj: T): Array<T[keyof T]> { return Object.keys(enumObj) // 过滤掉数字枚举的反向映射键 .filter(key => isNaN(Number(key))) .map(key => enumObj[key as keyof T]) }
内容的提问来源于stack exchange,提问作者Evanss
相关产品推荐
相关产品推荐

