You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何实现类似数组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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.16 17:07:11