如何在TypeScript中将元组映射为另一个强类型元组?
TypeScript 实现源元组到强类型目标元组的映射
要让映射后的结果成为强类型元组,需要结合类型编程和泛型约束实现,核心是让TypeScript推导出拼接后的精确元组结构,而非宽泛的数组类型。
步骤1:定义元组映射类型工具
编写递归条件类型,遍历源元组的每个元素,将其在映射表中对应的数组展开并拼接成目标元组类型:
type MapTuple< T extends readonly string[], M extends Record<string, readonly any[]> > = T extends [infer First, ...infer Rest extends readonly string[]] ? [...M[First], ...MapTuple<Rest, M>] : [];
这个类型会逐个处理源元组元素,把每个元素对应的映射数组展开,最终合并成完整的元组类型。
步骤2:实现类型安全的映射函数
封装泛型函数,让返回值类型直接对应上述MapTuple类型,运行时逻辑保持原有的reduce逻辑:
function mapTuple<T extends readonly string[], M extends Record<string, readonly any[]>>( tuple: T, map: M ): MapTuple<T, M> { return tuple.reduce((acc, e) => { acc.push(...map[e]); return acc; }, [] as any); }
这里用as any临时绕过类型检查——reduce本身返回数组类型,但我们已通过MapTuple在类型层面保证了结果的元组结构正确性。
步骤3:生成强类型元组
调用函数即可得到带有精确类型的元组:
const t1 = ["a", "b", "c"] as const; const nameMap = { "a": [], "b": ["j"], "c": ["k", "l"], } as const; const t2 = mapTuple(t1, nameMap); // t2 类型自动推导为 readonly ["j", "k", "l"]
如果需要可变元组,可将返回类型调整为[...MapTuple<T, M>],或对结果做解构后断言。
替代方案:直接类型断言
若不想封装函数,可先计算目标类型,再对reduce结果做类型断言:
type TargetTuple = MapTuple<typeof t1, typeof nameMap>; const t2 = [...t1.reduce((acc, e) => { acc.push(...nameMap[e]); return acc; }, [])] as TargetTuple;
此时t2的类型同样为["j", "k", "l"]。
内容的提问来源于stack exchange,提问作者Duplicate content
相关产品推荐
相关产品推荐

