Typescript adding types to EventEmitter
08:42 24 Apr 2021

I am trying to make my code more readable and concise.

The biggest problem I am currently having is with the EventEmitter class. Every time I create a new class that uses EventEmitter I have to declare all the functions of the EventEmitter to make the class easier to understand and use.

Ex:

interface Hello {
    addListener(event: 'hi', listener: (message: string) => void): this;
    on(event: 'hi', listener: (message: string) => void): this;
    ...
}

class Hello extends EventEmitter {
    constructor() { super(); }
}

I have searched around for a solution but I couldn't find anything that suits me so I tryed to come up with my own.

interface EventEmitterEvents {
    [event: string]: any[];
}

interface EventEmitterType extends EventEmitter {
    addListener(event: K, listener: (...args: T[K]) => void): this;
    on(event: K, listener: (...args: T[K]) => void): this;
    ...
}

class Hello extends EventEmitter implements EventEmitterType<{'hi': [string]}> { ... }

But when I try to implement the interface EventEmitterType it throws an error

types of property 'addListener' are incompatible

I have figured out that for some reason in the 'addListener' and functions alike, type event is said to be 'string' | 'symbol' | 'number' which is incompatible with the EventEmitter where it is 'string' | 'symbol' but in the EventEmitterEvents I have defined that event is of type 'string'.

Question: Is there any way to fix this, and if not, is there any other way of recreating this functionality (not having to type all those functions)?

Edit: If I set event argument to 'string' it will still throw error because of listener which is also incompatible with addListener saying 'any[]' is not assignable to type 'T[K]'.

node.js typescript