Hello. Earlier this week, I posted the same error as I have now and it was temporarily fixed because I removed generics from this class. I was unable to figure out how to reproduce this error when I originally had it, but now I did and because of that, I will repost it with the playground link.
So I created my own typings for EventEmitter by events to support strict typings of each emitted event. I will post what I created for reference:
export type DefaultEventHolder = { [E: string]: (...args: any[]) => any };
export type EventHolder<E> = { [e in keyof E]: (...args: any[]) => any; };
export declare interface TypedEmitter<Events extends EventHolder<Events> = DefaultEventHolder> {
addListener<E extends keyof Events>(event: E, listener: Events[E]): this;
prependListener<E extends keyof Events>(event: E, listener: Events[E]): this;
prependOnceListener<E extends keyof Events>(event: E, listener: Events[E]): this;
removeListener<E extends keyof Events>(event: E, listener: Events[E]): this;
removeAllListeners(event?: keyof Events): this;
emit<E extends keyof Events>(event: E, ...args: Parameters<Events[E]>): boolean;
eventNames<E extends keyof Events>(): E[];
off<E extends keyof Events>(event: E, listener: Events[E]): this;
on<E extends keyof Events>(event: E, listener: Events[E]): this;
once<E extends keyof Events>(event: E, listener: Events[E]): this;
getMaxListeners(): number;
listenerCount(type: keyof Events): number;
listeners<E extends keyof Events>(type: E): Events[E][];
rawListeners<E extends keyof Events>(type: E): Events[E][];
setMaxListeners(num: number): this;
}
So while attempting to use this custom declaration, I try attaching my own events to this class. In the method TypedEmitter#emit(), the compiler is properly understanding the keys of my event type in the first argument, but ...args, which is typed as Parameters<Events[E]>, errors when calling emit with values that clearly match the parameters of Events[E].
// ProviderEvents
export type ProviderEvents<S extends Structure> = {
load: (structure: S) => any;
remove: (structure: S) => any;
};
// EE is a generic that allows you to input more events while combining both 'ProviderEvents' and 'EE'
export class Provider<S extends Structure, E extends EventHolder<E> = {}> extends (EventEmitter as { new<S extends Structure, E extends EventHolder<E> = {}>(): TypedEmitter<ProviderEvents<S> & E> })<S, ProviderEvents<S> & E> implements Required<ProviderOptions<S>>
this.emit("load", structure /* Type: S */);
// ^ ok ^ error [but matches Parameters<ProviderEvents<S>["load"]>]
To go more in depth with the error, I attempted to intersect ProviderEvents<S> & EE and also did try a union ProviderEvents<S> | EE, but this only errored on event argument.
TS2345: Argument of type [S] is not assignable to parameter of type Parameters<(ProviderEvents<S> & EE)["load"]>