Skip to content

Instantly share code, notes, and snippets.

@hamzakaya
Last active April 2, 2022 07:19
Show Gist options
  • Save hamzakaya/e8b6bb4cc4153b2aa9ad6404b0bcf961 to your computer and use it in GitHub Desktop.
Save hamzakaya/e8b6bb4cc4153b2aa9ad6404b0bcf961 to your computer and use it in GitHub Desktop.
Fire Event (pub/sub/unsub)
type EventType = string | symbol
type Handler<T = unknown> = (event: T) => void
type OtherHandler<T = Record<string, unknown>> = (
type: keyof T,
event: T[keyof T],
) => void
type EventHandlerList<T = unknown> = Array<Handler<T>>
type OtherHandlerList<T = Record<string, unknown>> = Array<OtherHandler<T>>
type EventHandlerMap<Events extends Record<EventType, unknown>> = Map<
keyof Events | '*',
EventHandlerList<Events[keyof Events]> | OtherHandlerList<Events>
>
interface Emitter<Events extends Record<EventType, unknown>> {
all: EventHandlerMap<Events>
sub<Key extends keyof Events>(type: Key, handler: Handler<Events[Key]>): void
sub(type: '*', handler: OtherHandler<Events>): void
unsub<Key extends keyof Events>(
type: Key,
handler?: Handler<Events[Key]>,
): void
unsub(type: '*', handler: OtherHandler<Events>): void
pub<Key extends keyof Events>(type: Key, event: Events[Key]): void
pub<Key extends keyof Events>(
type: undefined extends Events[Key] ? Key : never,
): void
}
export default function fireEvent<Events extends Record<EventType, unknown>>(
all?: EventHandlerMap<Events>,
): Emitter<Events> {
type DynamicEventHandler =
| Handler<Events[keyof Events]>
| OtherHandler<Events>
all = all || new Map()
return {
all,
pub<Key extends keyof Events>(type: Key, evt?: Events[Key]) {
let handlers = all!.get(type)
if (handlers) {
;(handlers as EventHandlerList<Events[keyof Events]>)
.slice()
.map((handler) => handler(evt!))
}
handlers = all!.get('*')
if (handlers) {
;(handlers as OtherHandlerList<Events>)
.slice()
.map((handler) => handler(type, evt!))
}
},
sub<Key extends keyof Events>(type: Key, handler: DynamicEventHandler) {
const handlers: Array<DynamicEventHandler> | undefined = all!.get(type)
if (handlers) handlers.push(handler)
else all!.set(type, [handler] as EventHandlerList<Events[keyof Events]>)
},
unsub<Key extends keyof Events>(type: Key, handler?: DynamicEventHandler) {
const handlers: Array<DynamicEventHandler> | undefined = all!.get(type)
if (handlers) {
if (handler) handlers.splice(handlers.indexOf(handler) >>> 0, 1)
else all!.set(type, [])
}
},
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment