简体   繁体   English

打字稿推断函数参数联合

[英]Typescript infer function parameter unions

I currently have an interface with overloaded functions like so: 我目前有一个带有重载函数的接口,如下所示:

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;
}

I am trying to get the union type of event names like so: 我试图得到这样的联合类型的事件名称:

eventName1 | eventName1 | eventName2 | eventName2 | ... ...

I have tried the following, but when I infer the type it seems to only pick one of the name values and not a union of all of them. 我尝试过以下内容,但是当我推断出它的类型时,它似乎只选择了一个名称值,而不是所有这些名称的联合。

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'

I have also tried using an accumulator type to keep track of the unions, but Typescript doesnt allow recursive generics. 我也尝试使用累加器类型来跟踪联合,但Typescript不允许递归泛型。

Any ideas on how I can accomplish this? 有关如何实现这一目标的任何想法?

Edit: The interface with the overloaded definitions exists in an external module. 编辑:具有重载定义的接口存在于外部模块中。 I am trying to avoid c+ping from the external definitions to my definitions, and instead have it build the type automatically. 我试图避免从外部定义到我的定义的c + ping,而是让它自动构建类型。

This doesn't need to be a separate answer, but it's hard to get this in a comment: overloads specifically do not work the way you want with type inference in conditional types : 这不需要是一个单独的答案,但很难在评论中得到这个: 在条件类型中,重载特别是不能按照你想要的方式使用类型推断

When inferring from a type with multiple call signatures (such as the type of an overloaded function), inferences are made from the last signature (which, presumably, is the most permissive catch-all case). 当从具有多个呼叫签名的类型(例如,重载函数的类型)推断时,从最后一个签名(可能是最宽松的全部捕获的情况)进行推断。 It is not possible to perform overload resolution based on a list of argument types. 无法基于参数类型列表执行重载解析。

 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 

If you can't turn the overloads into a single function with a union of parameters (using conditional types to get listener for "eventName6" correct), then I don't know of a way to do this programmatically. 如果你不能使用参数联合将重载转换为单个函数(使用条件类型来获取"eventName6" listener器正确),那么我不知道以编程方式执行此操作的方法。

I don't think you can. 我认为你不能。 Using type infer with this example: 使用此示例的类型推断:

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;

It blames about x is not void, but one of the possible ReturnType of on in IEvents is 200. Looks like it only tries with the latest one. 它归咎于x不是无效的,但IEvents中可能的返回类型之一是200.看起来它只尝试使用最新版本。

So I guess that if you try to do something similar with the first argument of the function, it will only grab the latest one. 所以我想如果你尝试用函数的第一个参数做类似的事情,它只会抓住最新的一个。

You have here the definition of ReturnType: 你在这里有ReturnType的定义:

https://github.com/Microsoft/TypeScript/blob/release-2.8/lib/lib.d.ts#L1386 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