npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

strict-event-emitter-types

v2.0.0

Published

Strictly and safely type any EventEmitter-like interface on any object

Downloads

692,974

Readme

Typed Event Emitter

NOTE: REQUIRES TYPESCRIPT 3.0

A TypeScript library for strongly typed event emitters in 0 kB. Declare events using a simple interface mapping event names to their payloads to get stricter versions of emit, on, and other common EventEmitter APIs. Works with any kind of EventEmitter.

Installation

npm i strict-event-emitter-types

Example

import StrictEventEmitter from 'strict-event-emitter-types';

// define your events
interface Events {
  request: (request: Request, response: Response) => void;
  done: void;
}

// grab an event emitter
import { EventEmitter } from 'events';

// Create strict event emitter types
let ee: StrictEventEmitter<EventEmitter, Events> = new EventEmitter;

// now enjoy your strongly typed EventEmitter API!🎉

ee.on('request', (r, resp) => ... );
// r and resp are contextually typed to Request and Response

ee.on('somethingElse');
// Error: unknown event

ee.on('done', x => x);
// Error: The 'done' event does not have a payload

ee.emit('request', new Request());
// Error: missing event payload (the response)

ee.emit('request', new Request(), false);
// Error: incorrect payload type

Usage

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 Events {
  req: (request: Request, response: 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 number.

StrictEventEmitter<TEmitterType, TEventRecord, TEmitRecord>

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

  1. TEmitterType: Your EventEmitter type (e.g. node's EventEmitter or socket.io 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 socket.io:

// create types representing the server side and client
// side sockets
export type ServerSocket =
  StrictEventEmitter<SocketIO.Socket, EventsFromServer, EventsFromClient>;
export type ClientSocket =
  StrictEventEmitter<SocketIOClient.Socket, EventsFromClient, EventsFromServer>;

// 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 */, ...)
Usage with Subclasses

To subclass an EventEmitter you need to cast the base EventEmitter to the strict EventEmitter before extending:

type MyEmitter = StrictEventEmitter<EventEmitter, Events>;

class MyEventEmitter extends (EventEmitter as { new(): MyEmitter }) {
  doEmit() {
    this.emit(...); // strict
  }
}

StrictBroadcast<TStrictEventEmitter>

A type for a function which takes (and strictly checks) an emit event and a payload. TStrictEventEmitter is the event emitter type instantiated from StrictEventEmitter.

Useful for broadcast abstractions. It is not possible to contextually type assigments to this type, so your declarations will look something like this:

import { StrictBroadcast } from 'strict-event-emitter-types';

const broadcast: StrictBroadcast<ServerSocket> = function(
  event: string,
  payload?: any
) {
  // ...
};

Note that the loose types for event and payload only apply inside the broadcast function (consumers will see a much stricter signature). Declaring more precise parameter types or narrowing using type guards would allow strongly-typed dispatching to emitters.