Created
October 24, 2019 07:35
-
-
Save bramblex/6741b50e97259de73d10f4458f6cd414 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
type BaseEventMap = { [event: string]: [] } | |
type EventListener<EventMap extends BaseEventMap, Event extends keyof EventMap> | |
= (...args: EventMap[Event]) => any | |
type EventListenerItem<EventMap extends BaseEventMap, Event extends keyof EventMap> = { | |
once: boolean | |
listener: EventListener<EventMap, Event> | |
} | |
type Events<EventMap extends BaseEventMap> = { | |
[Event in keyof EventMap]?: EventListenerItem<EventMap, Event>[] | |
} | |
export class EventEmitter<EventMap extends BaseEventMap> { | |
private _events: Events<EventMap> = {} | |
emit<Event extends keyof EventMap>(event: Event, ...args: EventMap[Event]): boolean { | |
const listeners = this._events[event] | |
if (listeners && listeners.length > 0) { | |
listeners.forEach(({ listener }) => listener(...args)) | |
this._events[event] = listeners.filter(({ once }) => !once) | |
return true | |
} else { | |
return false | |
} | |
} | |
on<Event extends keyof EventMap>(event: Event, listener: (...args: EventMap[Event]) => any): this { | |
const listeners = this._events[event] | |
const item = { listener, once: false } | |
if (listeners) { | |
listeners.push(item) | |
} else { | |
this._events[event] = [item] | |
} | |
return this | |
} | |
once<Event extends keyof EventMap>(event: Event, listener: (...args: EventMap[Event]) => any): this { | |
const listeners = this._events[event] | |
const item = { listener, once: true } | |
if (listeners) { | |
listeners.push(item) | |
} else { | |
this._events[event] = [item] | |
} | |
return this | |
} | |
off<Event extends keyof EventMap>(event?: Event, listener?: (...args: EventMap[Event]) => any): this { | |
if (!event) { | |
this._events = {} | |
} else if (!listener) { | |
delete this._events[event] | |
} else { | |
const listeners = this._events[event] | |
if (listeners) { | |
this._events[event] = listeners.filter(item => item.listener !== listener) | |
} | |
} | |
return this | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment