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 | 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.
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.
Similar to JavaScript, to pass a function as a parameter in TypeScript, define a function expecting a parameter that will receive the callback function, then trigger the callback function inside the parent function.
TypeScript infers types of variables when there is no explicit information available in the form of type annotations. Types are inferred by TypeScript compiler when: Variables are initialized. Default values are set for parameters.
What does ?: mean in TypeScript? Using a question mark followed by a colon ( ?: ) means a property is optional. That said, a property can either have a value based on the type defined or its value can be undefined .
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With