I have a base class EventEmitter
, which has the on
method to bind handlers on specific events:
class EventEmitter {
on(event: string, handler: Function) {
/* add handler internally */
}
protected emit(event: string, ...args) {
/* call all handlers listening on event */
}
}
Now I have various subclasses, which can emit different events with different arguments. I'd like to "declare" which events can be emitted by that specific class:
class MyClass extends EventEmitter {
on(event: 'event1', handler: (arg1: number) => void): void;
on(event: 'event2', handler: (arg1: string, arg2: number) => void): void;
}
So my sub class may emit the events event1
and event2
, but this does not seem to be the right way to specify. TypeScript (tsc 1.8) is compaining:
error TS2415: Class 'MyClass' incorrectly extends base class 'EventEmitter'.
Types of property 'on' are incompatible.
Type '(event: "event1", handler: (arg1: number) => void) => void' is not assignable to type '(event: string, handler: Function) => void'.
Type '(event: "event1", handler: (arg1: number) => void) => void' provides no match for the signature '(event: string, handler: Function): void'
error TS2382: Specialized overload signature is not assignable to any non-specialized signature.
error TS2391: Function implementation is missing or not immediately following the declaration.
So, what is the intended way to specify the events my class can emit?
EDIT: I've found the name of what I was looking for: Specialized Signatures. However, it seems to be meant for interfaces only, and not for new TypeScript code.
Now I've found anothother question about the same issue from 2015, however the solution there does not look quite right. So, are there other ways to do it in TypeScript today?
what is the intended way to specify the events my class can emit?
Instead of using a single event stream that contains all the types its easier to have a separate event stream for each type.
This is a concept I call TypedEvent
. One example project that uses it is http://alm.tools/
Implementation : https://github.com/alm-tools/alm/blob/55a8eb0f8ee411a506572abce92085235658b980/src/common/events.ts#L20-L72
Here is an example usage : https://github.com/alm-tools/alm/blob/55a8eb0f8ee411a506572abce92085235658b980/src/server/lang/errorsCache.ts#L10
export let errorsUpdated = new TypedEvent<ErrorsUpdate>();
// emit:
errorsUpdated.emit({} /* this will be type checked */);
// consume:
errorsUpdated.on((x)=>null); // x has the correct inferred type
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