繁体   English   中英

打字稿推断函数参数联合

[英]Typescript infer function parameter unions

我目前有一个带有重载函数的接口,如下所示:

export interface IEvents {
  method(): boolean;
  on(name: 'eventName1', listener: (obj: SomeType) => void): void;
  on(name: 'eventName2', listener: (obj: SomeType) => void): void;
  on(name: 'eventName3', listener: (obj: SomeType) => void): void;
  on(name: 'eventName4', listener: (obj: SomeType) => void): void;
  on(name: 'eventName5', listener: (obj: SomeType) => void): void;
  on(name: 'eventName6', listener: () => void): void;
  on(name: 'eventName7', listener: (obj: SomeType) => void): void;
  on(name: 'eventName8', listener: (obj: SomeType) => void): void;
}

我试图得到这样的联合类型的事件名称:

eventName1 | eventName2 | ...

我尝试过以下内容,但是当我推断出它的类型时,它似乎只选择了一个名称值,而不是所有这些名称的联合。

export type TEventExtension<T extends IEvents> {
  [K in keyof T]: K extends 'on' ? TEventListenerName<T[K]> : never;
}[keyof T];
export type TEventListenerName<T> = T extends (name: infer N, listener: (obj?: infer E) => void) => void ? N : never;
const ext: TEventExtension<IEvents> = void 0 as any; // Type: 'eventName8'

我也尝试使用累加器类型来跟踪联合,但Typescript不允许递归泛型。

有关如何实现这一目标的任何想法?

编辑:具有重载定义的接口存在于外部模块中。 我试图避免从外部定义到我的定义的c + ping,而是让它自动构建类型。

这不需要是一个单独的答案,但很难在评论中得到这个: 在条件类型中,重载特别是不能按照你想要的方式使用类型推断

当从具有多个呼叫签名的类型(例如,重载函数的类型)推断时,从最后一个签名(可能是最宽松的全部捕获的情况)进行推断。 无法基于参数类型列表执行重载解析。

 declare function foo(x: string): number; declare function foo(x: number): string; declare function foo(x: string | number): string | number; type T30 = ReturnType<typeof foo>; // string | number 

如果你不能使用参数联合将重载转换为单个函数(使用条件类型来获取"eventName6" listener器正确),那么我不知道以编程方式执行此操作的方法。

我认为你不能。 使用此示例的类型推断:

interface SomeType {

}

export interface IEvents {
  method(): boolean;
  on(name: "eventName1", listener: (obj: SomeType) => void): 13;
  on(name: "eventName2", listener: (obj: SomeType) => void): void;
  on(name: "eventName3", listener: (obj: SomeType) => void): undefined;
  on(name: "eventName4", listener: (obj: SomeType) => void): 14;
  on(name: "eventName5", listener: (obj: SomeType) => void): 10;
  on(name: "eventName6", listener: () => void): "hola";
  on(name: "eventName8", listener: (obj: SomeType) => void): 200;
  on(name: "eventName7", listener: (obj: SomeType) => void): void;
}

const x: ReturnType<IEvents["on"]> = 200;

它归咎于x不是无效的,但IEvents中可能的返回类型之一是200.看起来它只尝试使用最新版本。

所以我想如果你尝试用函数的第一个参数做类似的事情,它只会抓住最新的一个。

你在这里有ReturnType的定义:

https://github.com/Microsoft/TypeScript/blob/release-2.8/lib/lib.d.ts#L1386

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM