如何获取TypeScript中const enum的大小?
如何计算TypeScript const enum的大小?
假设我们定义了这样的const enum:
const enum Fruit { Apple = 1, Banana, Carrot, Dragonfruit }
它的实际成员数量是4,但和普通enum不同,const enum编译后会被完全内联,不会生成对应的对象,所以没法用Object.keys(Fruit).length这类方法计算大小。
有人会推荐给enum加一个__SIZE成员来标记大小:
const enum Fruit { Apple = 1, Banana, Carrot, Dragonfruit, __SIZE }
然后通过Fruit.__SIZE获取值,但这个方案有两个明显问题:
- 联网场景下新增枚举项时,新成员会占用原来
__SIZE的数值位置,导致新成员ID和历史数据中的__SIZE/NULL插槽ID冲突,引发数据问题。 - 必须始终保证
__SIZE是最后一个成员,开发者容易遗忘同步,出错概率高。
下面是几个可行的替代方案,因为只需要在应用启动时计算一次,就算速度慢也没关系:
方案1:手动维护枚举值数组 + 类型校验
创建一个包含所有const enum成员的数组,直接取数组长度作为枚举大小。同时用TypeScript的类型约束强制数组覆盖所有成员,避免遗漏:
const enum Fruit { Apple = 1, Banana, Carrot, Dragonfruit } // 手动添加所有枚举值到数组 const fruitValues = [Fruit.Apple, Fruit.Banana, Fruit.Carrot, Fruit.Dragonfruit] as const; // 直接取数组长度作为枚举大小 const FRUIT_SIZE = fruitValues.length; // 结果为4 // 可选:添加类型校验,确保数组包含所有枚举成员 type AllFruitMembers = Exclude<Fruit, typeof fruitValues[number]>; // 如果有枚举成员没加到数组里,下面的类型会报错 type EnsureAllMembersIncluded = AllFruitMembers extends never ? true : false;
新增枚举项时,必须同步更新fruitValues数组,否则类型校验会报错,能有效避免遗漏。
方案2:利用类型元组推导枚举大小
通过TypeScript的类型工具把枚举的联合类型转为元组,推导元组的长度类型,再映射到运行时:
const enum Fruit { Apple = 1, Banana, Carrot, Dragonfruit } // 把枚举转为联合类型 type FruitUnion = Fruit; // 类型工具:将联合类型转为元组 type UnionToTuple<T, Acc extends unknown[] = []> = Exclude<T, Acc[number]> extends never ? Acc : UnionToTuple<T, [...Acc, Exclude<T, Acc[number]>]>; // 推导元组的长度,也就是枚举成员数量 type FruitSize = UnionToTuple<FruitUnion>['length']; // 运行时获取大小,类型会校验数值是否匹配 const FRUIT_SIZE = 4 as FruitSize;
当枚举新增成员时,FruitSize会自动更新为新的长度,如果手动写的数值和类型不匹配,编译会报错,保证正确性。
方案3:构建时生成大小常量
如果是大型项目,可以在构建流程中添加一个脚本,读取TypeScript文件中的const enum定义,解析并计算成员数量,自动生成一个包含大小常量的文件。比如用ts-morph这类工具来解析TS代码,避免手动维护的麻烦。
内容的提问来源于stack exchange,提问作者Ryan Peschel
相关产品推荐
相关产品推荐

