TypeScript 4.8.4:映射元组时如何优雅提取数字键?
优雅处理TypeScript元组映射中的数字键转换问题
需求说明
需要实现一个类型mapTuple,将输入元组转换为新元组,新元组的每个元素是原元组对应位置之前的所有元素组成的子元组。例如:
type mappedTuple = mapTuple<[10, 20, 30, 40]>; // 预期结果: [[], [10], [10, 20], [10, 20, 30]]
初始实现与报错
初始尝试的类型定义如下:
type mapTuple<T extends any[]> = {[key in keyof T]: SliceStartQuantity<T, 0, key>}
但触发类型错误:
Type '(number |
${number}) & key' does not satisfy the constraint 'number'.
Type '${number}& key' is not assignable to type 'number'.
原因是元组的keyof会同时返回数字类型索引(如0)和对应字符串字面量索引(如"0"),而SliceStartQuantity的第三个参数仅接受number类型,导致类型不兼容。
现有临时方案
通过硬编码的类型转换函数将字符串索引转为数字:
type castStringToNumber<T> = T extends '0' ? 0 : T extends '1' ? 1 : T extends '2' ? 2 : T extends '3' ? 3 : T extends '4' ? 4 : never; // 需手动扩展更多数字 type mapTuple<T extends any[]> = {[key in keyof T]:SliceStartQuantity<T,0,castStringToNumber<key>>}
该方案能正常工作,但扩展性差,需要手动添加更多数字分支,不够优雅。
更优雅的通用解决方案
利用TypeScript的模板字符串类型推断,实现一个通用的字符串转数字类型工具,无需硬编码:
// 通用字符串字面量转数字类型 type StringToNumber<T> = T extends `${infer N extends number}` ? N : T; type mapTuple<T extends any[]> = { [key in keyof T]: SliceStartQuantity<T, 0, StringToNumber<key>> };
原理说明
StringToNumber通过模板字符串推断,将匹配${number}格式的字符串字面量(如"0"、"1")转换为对应的数字类型(如0、1);对于原本就是数字类型的索引,则直接返回原类型。- 这样
SliceStartQuantity的第三个参数就能始终满足number类型约束,同时无需手动维护数字分支,扩展性更强。
内容的提问来源于stack exchange,提问作者themajashurka
相关产品推荐
相关产品推荐

