ee-ts v1.0.2
ee-ts
Type-safe event emitters (for TypeScript)
Features
- 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
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.
- 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
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.
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
7 years ago
7 years ago
7 years ago
7 years ago
7 years ago
7 years ago
7 years ago
7 years ago
7 years ago