What is strict-event-emitter-types?
The 'strict-event-emitter-types' npm package provides TypeScript types for strongly-typed event emitters. It allows developers to define event types and their corresponding payloads, ensuring type safety when emitting and listening to events.
What are strict-event-emitter-types's main functionalities?
Defining Typed Event Emitters
This feature allows you to define a typed event emitter with specific event names and their corresponding payload types. The code sample demonstrates how to create a custom event emitter class with typed events 'foo' and 'bar'.
const { EventEmitter } = require('events');
const { StrictEventEmitter } = require('strict-event-emitter-types');
interface Events {
foo: (arg: string) => void;
bar: (arg: number) => void;
}
class MyEmitter extends (EventEmitter as new () => StrictEventEmitter<EventEmitter, Events>) {}
const emitter = new MyEmitter();
emitter.on('foo', (arg) => console.log(arg));
emitter.emit('foo', 'Hello, world!');
Ensuring Type Safety
This feature ensures type safety by enforcing the correct argument types for each event. The code sample shows how TypeScript will throw an error if the argument type does not match the expected type for the event.
const { EventEmitter } = require('events');
const { StrictEventEmitter } = require('strict-event-emitter-types');
interface Events {
foo: (arg: string) => void;
bar: (arg: number) => void;
}
class MyEmitter extends (EventEmitter as new () => StrictEventEmitter<EventEmitter, Events>) {}
const emitter = new MyEmitter();
// TypeScript will throw an error if the argument type does not match
// emitter.emit('foo', 123); // Error: Argument of type 'number' is not assignable to parameter of type 'string'.
emitter.emit('foo', 'Hello, world!');
Typed Event Listeners
This feature allows you to define typed event listeners, ensuring that the callback functions match the expected argument types for each event. The code sample demonstrates how TypeScript will throw an error if the listener callback does not match the expected type.
const { EventEmitter } = require('events');
const { StrictEventEmitter } = require('strict-event-emitter-types');
interface Events {
foo: (arg: string) => void;
bar: (arg: number) => void;
}
class MyEmitter extends (EventEmitter as new () => StrictEventEmitter<EventEmitter, Events>) {}
const emitter = new MyEmitter();
// TypeScript will throw an error if the listener callback does not match the expected type
// emitter.on('foo', (arg: number) => console.log(arg)); // Error: Argument of type '(arg: number) => void' is not assignable to parameter of type '(arg: string) => void'.
emitter.on('foo', (arg: string) => console.log(arg));
Other packages similar to strict-event-emitter-types
typed-emitter
The 'typed-emitter' package provides a similar functionality by allowing you to create strongly-typed event emitters in TypeScript. It offers a more modern API and better integration with TypeScript's type system compared to 'strict-event-emitter-types'.
eventemitter3
The 'eventemitter3' package is a lightweight and fast event emitter implementation. While it does not provide built-in TypeScript type safety, it can be extended with custom TypeScript types to achieve similar functionality as 'strict-event-emitter-types'.
mitt
The 'mitt' package is a tiny functional event emitter. It is not strictly typed out of the box, but you can use TypeScript's type system to create type-safe event emitters similar to 'strict-event-emitter-types'.
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';
interface Events {
request: (request: Request, response: Response) => void;
done: void;
}
import { EventEmitter } from 'events';
let ee: StrictEventEmitter<EventEmitter, Events> = new EventEmitter;
ee.on('request', (r, resp) => ... );
ee.on('somethingElse');
ee.on('done', x => x);
ee.emit('request', new Request());
ee.emit('request', new Request(), false);
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:
- Function type: Parameters are the event payload. The return type is ignored.
void
: A shortcut for an event with no payload, i.e. () => void
- 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:
- TEmitterType: Your EventEmitter type (e.g. node's EventEmitter or socket.io socket)
- TEventRecord: A type mapping event names to event payloads
- 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:
export type ServerSocket =
StrictEventEmitter<SocketIO.Socket, EventsFromServer, EventsFromClient>;
export type ClientSocket =
StrictEventEmitter<SocketIOClient.Socket, EventsFromClient, EventsFromServer>;
let serverSocket: ServerSocket = new SocketIO.Socket();
serverSocket.on(, ...)
serverSocket.emit(, ...)
let clientSocket: ClientSocket = new SocketIOClient.Socket();
clientSocket.on(, ...)
clientSocket.emit(, ...)
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(...);
}
}
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.