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

TypeScript泛型与Record类型映射问题:批量转换Action函数类型

问题解决:批量转换Actions对象的类型

需求说明

我有如下结构的对象:

const actions = {
    foo: (state: string, action: {payload: string}) => {},
    bar: (state: string, action: {payload: number}) => {},
    baz: (state: string, action: {payload: boolean}) => {},
    qux: (state: string) => {}
}

同时我定义了如下泛型类型:

type ActionMapper<T> = T extends (state: any, action: infer Action) => any 
    ? Action extends {payload: infer P} 
        ? (payload: P) => void 
        : VoidFunction 
    : never

这个泛型可以提取单个函数(比如actions.foo())中action.payload的类型,生成对应的函数类型。我现在需要实现一个泛型,对整个actions对象完成同样的类型转换。

已尝试方案

我试过定义下面这个泛型:

type ActionsMapper<A> = Record<keyof A, ActionMapper<A[keyof A]>>

但结果不符合预期:它把所有函数的参数类型提取出来生成了联合类型,而不是为每个属性生成单独的正确类型(比如我期望mappedActions.foo()的类型是(payload: string) => void)。


解决方案

要实现针对对象每个属性单独处理的类型转换,需要使用映射类型配合索引访问的分布式条件类型,也就是在映射时对每个属性单独应用ActionMapper:

type ActionsMapper<A> = {
  [K in keyof A]: ActionMapper<A[K]>
}

原理说明

原来的Record<keyof A, ActionMapper<A[keyof A]>>问题在于,A[keyof A]会先获取所有属性值的联合类型,然后ActionMapper对这个联合类型进行分布式条件类型处理,最终得到的是所有可能结果的联合类型,再把这个联合类型赋值给每个属性,导致所有属性的类型都一样。

而使用映射类型[K in keyof A]时,会遍历对象的每个键K,单独对A[K](也就是每个属性对应的函数类型)应用ActionMapper,这样每个属性都会得到对应的正确类型。

验证结果

用这个新的ActionsMapper处理actions对象,得到的类型会是:

type MappedActions = ActionsMapper<typeof actions>
// 等价于:
// {
//   foo: (payload: string) => void;
//   bar: (payload: number) => void;
//   baz: (payload: boolean) => void;
//   qux: VoidFunction;
// }

内容的提问来源于stack exchange,提问作者ElohmroW

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.07 23:07:20