TypeScript中如何从动态数组生成字符串字面量类型
问题原理
TypeScript 类型系统完全在编译阶段执行,无法感知运行时Array.from生成数组的具体长度,你写的ReadonlyArray<number>类型本身不携带固定长度的字面量信息,因此keyof A只能拿到通用number类型,推导出来的ScaleKeys只会是${number}x,无法得到具体的索引字符串字面量联合。
该需求可以通过提前指定长度泛型的方案实现,同时满足运行时动态生成数组、编译时自动生成目标字面量类型的要求,不需要手动声明长静态数组。
实现代码
// 类型工具:生成 0 ~ L-1 的数字联合类型 type NumRange<L extends number, Temp extends number[] = []> = Temp['length'] extends L ? Temp[number] : NumRange<L, [...Temp, Temp['length']]>; // 类型工具:根据数组长度直接生成目标 `${数字}x` 联合类型 type ScaleKeysByLength<L extends number> = `${NumRange<L>}x`; // 运行时工具:生成指定长度的数组,同时绑定长度类型 function createScaleArray<L extends number>( length: L, fillCallback: (index: number) => number = (i) => i ): readonly number[] & { length: L } { return Array.from({ length }, (_, idx) => fillCallback(idx)) as const; }
使用示例
// 生成长度为20、值为0/0.5/1/.../9.5的数组,和你原来的步长规则对齐 const spacing = createScaleArray(20, i => i * 0.5); // 直接生成长度20对应的索引字符串联合类型 type SpaceKeys = ScaleKeysByLength<20>; // 类型校验测试 const validKey1: SpaceKeys = '0x'; // 正常通过 const validKey2: SpaceKeys = '19x'; // 正常通过 const invalidKey: SpaceKeys = '20x'; // 编译报错,超出索引范围
内容的提问来源于stack exchange,提问作者dagda1
相关产品推荐
相关产品推荐

