Type-safe event emitters (for TypeScript)
- strict event names
- type-checking for emitted data
- flexible
listeners()
generator method - add/remove listeners during emit
- great for sub-classing
- one-time listeners
- default handlers
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"'.
This library was designed with subclassing in mind.
- The internal cache is non-enumerable
- Few public methods:
on
,one
,off
,emit
,listeners
- Override
_onEventHandled(key: string)
to know when an event has at least one listener - Override
_onEventUnhandled(key: string)
to know when an event has no listeners
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)
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.
Add a listener to the given event key.
Use the one
method to add a one-time listener.
Returns: the fn
argument
Add every listener value to its associated event key.
Use the one
method to add one-time listeners.
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 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
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.
Set the default handler for an event key.
The default handler is called when no other listeners exist for the same event key.
Get an array of event keys that have listeners.
Get the number of listeners an event has.
Check if an event has listeners.
Returns: true when the given event key has >= 1
listener.