I had struggled with this a few times... The cast to the interface is fine when you just want an emitter, but I had issues extending EventEmitter. #30 gets to the root of it. There's really not a way to have an abstract emitter such as:
import EventEmitter from 'node:events'
import TypedEmitter, { EventMap } from 'typed-emitter'
// Base class expressions cannot reference class type parameters. ts(2562)
// V
class BaseEmitter<T extends EventMap> extends (EventEmitter as new () => TypedEmitter<T>) {
// ...
}
I did ultimately find a really ugly way to get a class definition that could be extended as normal:
import NodeEventEmitter from 'node:events'
import TypedEventEmitter from 'typed-emitter'
const EventEmitter = NodeEventEmitter as unknown as {
new <Events extends EventMap>(): TypedEventEmitter<Events> extends infer O
? { [K in keyof O]: O[K] }
: never
}
export default class TypedEmitter<
Events extends EventMap,
> extends EventEmitter<Events> {}
I think the library could export a class without making things very complicated, though. Have a look at the linked PR and see what you think.
The only thing I can see as being a problem is if there is some use for this outside of node. Even then, you could likely have the original as a separate definition and leverage the exports field to accommodate that like:
I had struggled with this a few times... The cast to the interface is fine when you just want an emitter, but I had issues extending
EventEmitter
. #30 gets to the root of it. There's really not a way to have an abstract emitter such as:I did ultimately find a really ugly way to get a class definition that could be extended as normal:
I think the library could export a class without making things very complicated, though. Have a look at the linked PR and see what you think.
The only thing I can see as being a problem is if there is some use for this outside of node. Even then, you could likely have the original as a separate definition and leverage the
exports
field to accommodate that like: