如何实现类似数组map的TypeScript联合类型转换?
TypeScript 泛型Map实现与infer写法问题解析
1. 通用泛型Map类型的实现
要实现类似数组map方法的通用泛型,我们可以定义一个可复用的泛型类型,接收元组和事件数据映射两个参数,通过分布式条件类型逐个处理元组成员:
interface EventDataMap { "aaa": string; "bbb": number; "ccc": boolean; } type t1 = ["aaa", "bbb"] // 通用泛型:将元组成员映射为指定结构的联合类型 type MapTupleToUnion<T extends readonly string[], M extends Record<string, unknown>> = T[number] extends infer K ? K extends keyof M ? { event_name: K, value: M[K] } : never : never; // 生成目标类型 type resultT = MapTupleToUnion<t1, EventDataMap>; // 最终结果:{ event_name: "aaa", value: string } | { event_name: "bbb", value: number }
这个泛型的核心逻辑:
T[number]将输入元组转换为联合类型- 通过
K extends keyof M触发分布式条件类型,让联合类型的每个成员单独参与类型计算 - 为每个成员生成对应的对象结构,最终自动合并为联合类型
该泛型适配任意元组和数据映射结构,无需修改原有接口,通用性强。
2. 原infer写法失效的原因
你尝试的type rt = t1[number] extends infer T ? {event_name: T, data: EventDataMap[T]} : never;无法生效,问题出在infer的推断逻辑:
当使用A extends infer T ? ...时,T会被推断为整个A的完整类型——也就是"aaa" | "bbb"这个联合类型,而非逐个推断联合类型的成员。此时EventDataMap[T]会被解析为EventDataMap["aaa" | "bbb"],即string | number,最终得到的是{event_name: "aaa" | "bbb", data: string | number},完全不是期望的联合对象类型。
而分布式条件类型的触发条件是T extends U ? ...(其中T是联合类型),TypeScript会自动遍历联合类型的每个成员单独计算,再合并结果。你之前的UnionToSomeObj能生效,正是因为T extends string触发了分布式逻辑。
另外,原代码中添加的[p: string]: any索引签名完全冗余——使用正确的分布式条件类型时,每个K都是EventDataMap的明确键,不会出现类型报错。
内容的提问来源于stack exchange,提问作者Autumn
相关产品推荐
相关产品推荐

