Need help with nest-emitter?
Click the “chat” button below for chat support from the developer who created it, or find similar developers for support.

About the developer

132 Stars 21 Forks MIT License 38 Commits 16 Opened issues


Strongly 💪🏼 Typed Eventemitter Module For Nestjs Framework 🦁

Services available


Need anything else?

Contributors list

Nest Emitter

Strongly 💪🏼 Typed Eventemitter Module For Nestjs Framework 🦁

Quick Overview

Ever wondered if there is a way to have a strongly typed way to use event emitter names ?

Ever wondered why your event emitter is not working as intended and then realized that there was a typo on your events name? if so, then this ones for you :smile: .


By Declaring events using a simple interface mapping event names to their payloads to get stricter versions of

, and other common EventEmitter APIs.

and not only that, it will work with any kind of

that implements


IMPORTANT: you will need typescript 3.0+

npm install nest-emitter


yarn add nest-emitter


As Normal Import

into your root module (aka


NestEmitterModule#forRoot(emitter: NodeJS.Events)
takes any event emitter that implements

For simplicity I will use nodejs built-in eventemitter, but of course you can use whatever you need.

// app.module.ts

import { Module } from '@nestjs/common'; import { AppController } from './app.controller'; import { AppService } from './app.service'; import { NestEmitterModule } from 'nest-emitter'; import { EventEmitter } from 'events'; @Module({ imports: [NestEmitterModule.forRoot(new EventEmitter())], controllers: [AppController], providers: [AppService], }) export class AppModule {}

Now it's time to define our events, let's add two events one called

and it's payload will be a string. and another one is
and it's payload will be function that has one arg of type
interface AppEvents {
  notification: string;
  // as a side note: that is equivalent to
  // newRequest: Express.Request;
  newRequest: (req: Express.Request) => void;

After that let's bring up our secret weapon; the

import { EventEmitter } from 'events';
import { StrictEventEmitter } from 'nest-emitter';

interface AppEvents { notification: string; newRequest: (req: Express.Request) => void; }

export type MyEventEmitter = StrictEventEmitter;

good good, now let's use it.

:+1: TIP: Keep all of your events in a separate file like


I will use it to send a notification when we receive a request

// app.controller.ts

import { Get, Controller, Req } from '@nestjs/common'; import { AppService } from './app.service'; import { InjectEventEmitter } from 'nest-emitter'; import { MyEventEmitter } from '';

@Controller() export class AppController { constructor( private readonly appService: AppService, @InjectEventEmitter() private readonly emitter: MyEventEmitter, ) {}

@Get() root(@Req() req: Express.Request): string { this.emitter.emit('notification', 'new req'); // this will throw an error at compile-time // as notification event only accepts string // this.emitter.emit('notification', 1234); this.emitter.emit('newRequest', req); return this.appService.root(); } }

Did you notice

? you guessed it, it's a helper decorator to get the instance of the underlying eventemitter.

now on the other side

import { Injectable, OnModuleInit } from '@nestjs/common';
import { InjectEventEmitter } from 'nest-emitter';
import { MyEventEmitter } from '';

@Injectable() export class AppService implements OnModuleInit { constructor(@InjectEventEmitter() private readonly emitter: MyEventEmitter) {} onModuleInit() { this.emitter.on('notification', async msg => await this.onNotification(msg)); this.emitter.on('newRequest', async req => await this.onRequest(req)); } root(): string { return 'Hello World!'; }

private async onNotification(msg: string) { console.log(OnNotification: ${msg}); }

private async onRequest(req: Express.Request) { console.log(OnRequest from: ${req['ip']}); } }

And that's it! Easy? now let's dive in.

In Depth

Event Records

Event records are interfaces or object types that map event names to the event's payload types. In the following example, three events are declared:

interface AppEvents {
  req: (request: Express.Request, response: Express.Response) => void;
  done: void;
  conn: Connection;

Each event shows one of three ways to type the event payloads:

  1. Function type: Parameters are the event payload. The return type is ignored.
  2. void
    A shortcut for an event with no payload, i.e.
    () => void
  3. Anything else: A shortcut for an event with one payload, for example
    (p: number) => void
    can be written as just


The default export. A generic type that takes three type parameters:

  1. TEmitterType: Your EventEmitter type (e.g. node's EventEmitter or socket)
  2. TEventRecord: A type mapping event names to event payloads
  3. TEmitRecord: Optionally, a similar type mapping things you can emit.

The third parameter is handy when typing web sockets where client and server can listen to and emit different events. For example, if you are using

// create types representing the server side and client
// side sockets
export type ServerSocket =
export type ClientSocket =

// elsewhere on server let serverSocket: ServerSocket = new SocketIO.Socket(); serverSocket.on(/* only events that are sent from the client are allowed /, ...) serverSocket.emit(/ only events that are emitted from the server are allowed */, ...)

// elsewhere on client let clientSocket: ClientSocket = new SocketIOClient.Socket(); clientSocket.on(/* only events that are sent from the server are allowed /, ...) clientSocket.emit(/ only events that are emitted from the client are allowed */, ...) </socketioclient.socket></socketio.socket>

For more information about

see @bterlson 's library


See CHANGELOG for more information.


You are welcome to contribute to this project, just open a PR.


  • Shady Khalifa (@shekohex) - Initial work
  • Brian Terlson (@bterlson) - strict event emitter types

See also the list of contributors who participated in this project.


This project is licensed under the MIT License - see the file for details.

We use cookies. If you continue to browse the site, you agree to the use of cookies. For more information on our use of cookies please see our Privacy Policy.