Home

Awesome

ee-ts

npm Build status codecov Bundle size Install size Code style: Prettier Donate

Type-safe event emitters (for TypeScript)

Features

 

Example

import { EventEmitter as EE } from 'ee-ts'

type User = { name: string }

// All possible events must be explicitly defined as methods here.
// The return type can be non-void because the `emit` method returns the last non-void value.
// The return type can never be required, because `void` is implicitly added to every event.
interface Events {
  login(user: User): void
  logout(): string
}

// Make your subclass generic to let users add their own events.
class App<T = {}> extends EE<T & Events> {
  // You _cannot_ emit user-added events from here, though.
  someMethod(this: App) {
    this.emit('logout')
  }
}

type UserEvents = { test(): void }
let app = new App<UserEvents>()

// Emit your custom event.
app.emit('test')

// The type of `user` is inferred.
app.on('login', user => {
  console.log(user.name) // user.name is string
})

// Invalid argument types are caught.
app.one('login', (invalid: boolean) => {}) // [ts] Type 'User' is not assignable to type 'boolean'.

// Invalid return values are caught.
app.one('logout', () => true) // [ts] Type 'boolean' is not assignable to type 'string | void'.

// Unknown event names are caught.
app.emit('invalid') // [ts] Argument of type '"invalid"' is not assignable to parameter of type '"login" | "logout"'.

 

Subclassing

This library was designed with subclassing in mind.

 

Disposables

When you pass an array as the last argument of on, one, or EE.unhandle, an object is pushed onto it. This object has a dispose(): void method, which you should call to remove the associated listener from its event.

This is a useful way of grouping listeners together.

import { EventEmitter, Disposable } from 'ee-ts'

const ee = new EventEmitter<{ foo(): void }>()

const disposables: Disposable[] = []

let count = 0
const fn = ee.on('foo', () => count++, disposables)

assert(disposables.length == 1)

disposables[0].dispose()
ee.emit('foo')

assert(count == 0)

 

API Reference

The type signatures below are not 100% accurate. They're here to give you a general idea of the API. Find the real type signatures in the source code or VS Code.

 

on(key: string, fn: Function, disposables?: Disposable[]): Function

Add a listener to the given event key.

Use the one method to add a one-time listener.

Returns: the fn argument

 

on(map: { [key: string]: Function }, disposables?: Disposable[]): this

Add every listener value to its associated event key.

Use the one method to add one-time listeners.

 

off(key: string, fn?: Function): this

Remove a listener for the given event key.

Omit the fn argument to remove all listeners for the given event key.

Call off('*') to remove all listeners for every event key.

 

emit(key: string, ...args: any[]): any

Emit an event to listeners associated with the given event key.

You can safely add/remove listeners from inside a listener.

Returns: last non-void value returned by a listener

 

listeners(key: string): IterableIterator<Function>

Create a generator of the listeners for the given event key.

Use this with for..of or spread it into an array. Read more about generators here.

 

Static methods

 

unhandle(ee: EventEmitter, key: string, fn: Function, disposables?: Disposable[]): Function

Set the default handler for an event key.

The default handler is called when no other listeners exist for the same event key.

 

keys(ee: EventEmitter): string[]

Get an array of event keys that have listeners.

 

count(ee: EventEmitter, key: string): number

Get the number of listeners an event has.

 

has(ee: EventEmitter, key: string): boolean

Check if an event has listeners.

Returns: true when the given event key has >= 1 listener.