/tiny-typed-emitter2

Fully type-checked NodeJS EventEmitter

Primary LanguageJavaScriptMIT LicenseMIT

tiny-typed-eventemitter2

This is a fork of tiny-typed-emitter for EventEmitter2.

Have your events and their listeners type-checked with no overhead.

npm version

Install

Simply add the dependency using npm:

$ npm i tiny-typed-emitter2

or using yarn:

$ yarn add tiny-typed-emitter2

Usage

  1. import tiny-typed-emitter2 library:
import { TypedEmitter } from 'tiny-typed-emitter2';
  1. define events and their listener signatures (note: quotes around event names are not mandatory):
interface MyClassEvents {
  'added': (el: string, wasNew: boolean) => void;
  'deleted': (deletedCount: number) => void;
}
  1. on this step depending on your use case, you can:
  • define your custom class extending EventEmitter:
    class MyClass extends TypedEmitter<MyClassEvents> {
      constructor() {
        super();
      }
    }
  • create new event emitter instance:
    const emitter = new TypedEmitter<MyClassEvent>();

Generic events interface

To use with generic events interface:

interface MyClassEvents<T> {
  'added': (el: T, wasNew: boolean) => void;
}

class MyClass<T> extends TypedEmitter<MyClassEvents<T>> {

}

Compatible subclasses with different events

The type of eventNames() is a superset of the actual event names to make subclasses of a TypedEmitter that introduce different events type compatible. For example the following is possible:

class Animal<E extends ListenerSignature<E>=ListenerSignature<unknown>> extends TypedEmitter<{spawn: () => void} & E> {
  constructor() {
    super();
  }
}

class Frog<E extends ListenerSignature<E>> extends Animal<{jump: () => void} & E> {
}

class Bird<E extends ListenerSignature<E>> extends Animal<{fly: () => void} & E> {
}

const animals: Animal[] = [new Frog(), new Bird()];

Compatible with NestJS

This library is compatible with @nestjs/event-emitter which uses EventEmitter2 under the hood. To use follow the instructions from:

https://docs.nestjs.com/techniques/events

With the following changes:

  1. Use the more specific event type instead of EventEmitter2. For example:
constructor(private eventEmitter: EventEmitter2) {}

becomes:

constructor(private eventEmitter: TypedEmitter<MyEvents>) {}
  1. Don't use the @OnEvent method decorator

Instead of doing this:

@OnEvent('some.event')
myHandler(event: MyCustomEventType) {}

You'll need to do this:

constructor(events: TypedEmitter<MyEvents>) {
  events.on('some.event', (event) => {
    // correct event type will automatically be available
  });
}

No Overhead

Library adds no overhead. All it does is it simply reexports renamed EventEmitter2 with customized typings. You can check lib/index.js to see the exported code.