Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Declaring events in a TypeScript class which extends EventEmitter

I have a class extends EventEmitter that can emit event hello. How can I declare the on method with specific event name and listener signature?

class MyClass extends events.EventEmitter {    emitHello(name: string): void {     this.emit('hello', name);   }    // compile error on below line   on(event: 'hello', listener: (name: string) => void): this; } 
like image 448
aleung Avatar asked Aug 25 '16 10:08

aleung


People also ask

How do I create a event in typescript?

You can use typed event emitter package for this. eg: import { EventEmitter } from 'tsee'; const events = new EventEmitter<{ foo: (a: number, b: string) => void, }>(); // foo's arguments is fully type checked events. emit('foo', 123, 'hello world');

Which is the commonly used events in EventEmitter?

EventEmitter Class When an EventEmitter instance faces any error, it emits an 'error' event. When a new listener is added, 'newListener' event is fired and when a listener is removed, 'removeListener' event is fired. EventEmitter provides multiple properties like on and emit.


Video Answer


2 Answers

Most usable way of doing this, is to use declare:

declare interface MyClass {     on(event: 'hello', listener: (name: string) => void): this;     on(event: string, listener: Function): this; }  class MyClass extends events.EventEmitter {     emitHello(name: string): void {         this.emit('hello', name);     } } 

Note that if you are exporting your class, both the interface and class have to be declared with the export keyword.

like image 168
SergeyK Avatar answered Sep 24 '22 14:09

SergeyK


to extend @SergeyK's answer, with this you can get type-checking and completion on both emit and on functions without repeating event types.

  1. Define event listener signatures for each event type:
interface MyClassEvents {   'add': (el: string, wasNew: boolean) => void;   'delete': (changedCount: number) => void; } 
  1. Declare interface which constructs types for MyClass, based on EventListeners (MyClassEvents) function signature:
declare interface MyClass {   on<U extends keyof MyClassEvents>(     event: U, listener: MyClassEvents[U]   ): this;    emit<U extends keyof MyClassEvents>(     event: U, ...args: Parameters<MyClassEvents[U]>   ): boolean; } 
  1. Simply define you class extending EventEmitter:
class MyClass extends EventEmitter {   constructor() {     super();   } } 

Now you will get type checking for on and emit functions:

enter image description here

enter image description here

Unfortunately you will get completion and type-checking only on those two functions (unless you define more functions inside MyClass interface).

To get more generic solution, you can use this package. note: it adds no runtime overhead.

import { TypedEmitter } from 'tiny-typed-emitter';  interface MyClassEvents {   'add': (el: string, wasNew: boolean) => void;   'delete': (changedCount: number) => void; }  class MyClass extends TypedEmitter<MyClassEvents> {   constructor() {     super();   } } 
like image 34
Binier Avatar answered Sep 25 '22 14:09

Binier