从这样的类型:

type Def = {
  m1(a1: A1, b1: B1): R1
  m2(a2: A2): R2
  m3(a3: A3, b3: B3, c3: C3): R3
}

我想要计算一个这样的类型:

type F =
  ((name: 'm1', a1: A1, b1: B1) => R1) &
  ((name: 'm2', a2: A2) => R2) &
  ((name: 'm2', a3: A3, b3: B3, c3: C3) => R3)

这是动态生成的Dispatcher方法的重载函数类型.

我设法添加了name参数,即:

type H = {
  m1: (name: 'm1', a1: A1, b1: B1) => R1,
  m2: (name: 'm2', a2: A2) => R2,
  m3: (name: 'm3', a3: A3, b3: B3, c3: C3) => R3,
}

通过简单的对象映射以及ParameterReturnType帮助器,但是我试图将其合并到单个调用签名中的所有try 都失败了.

(见playground link)

推荐答案

这里有一种可能的方法:

type IntersectMethods<T> = {
    [K in keyof T]: T[K] extends (...args: infer A) => infer R ?
    (x: ((name: K, ...args: A) => R)) => void :
    never
} extends Record<string, (x: infer I) => void> ? I : never

这使用conditional type inference并推断intersections而不是unions,因为要推断的类型已移动到逆变量位置(有关方差的更多信息,请参见Difference between Variance, Covariance, Contravariance and Bivariance in TypeScript).它本质上与Transform union type to intersection type中的技术相同,只是我们只找到方法,并 for each 方法添加一个name参数.

让我们来测试一下:

type Def = {
  m1(a1: A1, b1: B1): R1
  m2(a2: A2): R2
  m3(a3: A3, b3: B3, c3: C3): R3
}

type F = IntersectMethods<Def>
/* type F = 
     ((name: "m1", a1: A1, b1: B1) => R1) & 
     ((name: "m2", a2: A2) => R2) & 
     ((name: "m3", a3: A3, b3: B3, c3: C3) => R3)
*/

看上go 不错!

Playground link to code

Typescript相关问答推荐

TypeScript Page Routing在单击时不呈现子页面(React Router v6)

如果请求是流,如何等待所有响应块(Axios)

Redux—Toolkit查询仅在不为空的情况下添加参数

输入元素是类型变体的对象数组的正确方法是什么?'

有没有办法解决这个问题,类型和IntrinsicAttributes类型没有相同的属性?

如何使用一个字段输入对象,其中每个键只能是数组中对象的id属性,而数组是另一个字段?

仅针对某些状态代码重试HTTP请求

使用打字Angular 中的通用数据创建状态管理

类型脚本返回的类型包含无意义的泛型类型名称

有什么方法可以类型安全地包装import()函数吗?

API文件夹内的工作员getAuth()帮助器返回:{UserID:空}

react 路由不响应参数

Angular NG8001错误.组件只能在一个页面上工作,而不是在她的页面上工作

如何使对象同时具有隐式和显式类型

两个接口的TypeScript并集,其中一个是可选的

如何通过nx找到所有受影响的项目?

如何使用 runInInjectionContext 中的参数测试功能性路由防护

如何在由函数参数推断的记录类型中具有多个对象字段类型

const nav: typechecking = useNavigation() 和 const nav = useNavigation() 之间有什么区别?

通用可选函数参数返回类型