Skip to content

Instantly share code, notes, and snippets.

@adhrinae
Last active June 4, 2018 11:09
Show Gist options
  • Save adhrinae/c8417689c377344a38f0d085a5617056 to your computer and use it in GitHub Desktop.
Save adhrinae/c8417689c377344a38f0d085a5617056 to your computer and use it in GitHub Desktop.
Typescript Friendly Version of Mitt - https://github.com/developit/mitt
type EventHandler = (event?: any) => void
type WildCardEventHandler = (type: string, event?: any) => void
type EventHandlerList = EventHandler[]
type WildCardEventHandlerList = WildCardEventHandler[]
type AnyEventHandler = EventHandler | WildCardEventHandler
type AnyEventHandlerList = EventHandlerList | WildCardEventHandlerList
type EventHandlerMap = {
'*'?: WildCardEventHandlerList,
[type: string]: EventHandlerList
}
export default function mitt(all: EventHandlerMap = {}) {
const WILD_CARD = '*'
const getListByType = (handlerMap: EventHandlerMap, eventType: string): AnyEventHandlerList => {
if (eventType === WILD_CARD) {
handlerMap[WILD_CARD] = handlerMap[WILD_CARD] || []
return handlerMap[WILD_CARD] as WildCardEventHandlerList
} else {
handlerMap[eventType] = handlerMap[eventType] || []
return handlerMap[eventType]
}
}
const isEmptyHandlerList = (handlerList: AnyEventHandlerList) => handlerList.length === 0
return {
on(type: string, handler: AnyEventHandler) {
if (type === WILD_CARD) {
const evtHandlerList = getListByType(all, type) as WildCardEventHandlerList
evtHandlerList.push(handler)
} else {
const evtHandlerList = getListByType(all, type) as EventHandlerList
evtHandlerList.push(handler)
}
},
off(type: string, handler: AnyEventHandler) {
const eventList = all[type]
if (eventList) {
all[type] = eventList.filter(h => eventList.indexOf(h) < 0)
}
},
emit(type: string, evt: any) {
if (!isEmptyHandlerList(all[type])) {
getListByType(all, type).slice().forEach((handler: EventHandler) => handler(evt))
getListByType(all, WILD_CARD).slice().forEach((handler: WildCardEventHandler) => handler(type, evt))
}
}
}
}
let emitter = mitt()
const fakeEventFunc = (e: any) => {
console.log('Event Emitted!')
console.log('Let\'s make some changes');
return {
...e,
changes: 'awesome!'
}
}
const log = (eventName: string) => (e: any) => console.log(eventName, e)
const fooLog = log('foo')
emitter.on('foo', fooLog)
emitter.on('*', (type, e) => console.log(type, e))
emitter.on('bar', e => console.log(fakeEventFunc(e)))
const testObj = { a: 'b' }
emitter.emit('foo', testObj)
emitter.emit('bar', testObj)
emitter.off('foo', fooLog)
emitter.off('bar', fakeEventFunc)
emitter.emit('foo', testObj)
emitter.emit('bar', testObj)
/*
Result
=======================================
foo { a: 'b' }
foo { a: 'b' }
Event Emitted!
Let's make some changes
{ a: 'b', changes: 'awesome!' }
bar { a: 'b' }
*/
// Receive an Object, Return an Object Pattern (RORO)
// Reference: https://medium.freecodecamp.org/elegant-patterns-in-modern-javascript-roro-be01e7669cbd
type EventHandler = ({ type, event }: { type?: string, event?: any }) => void
type EventHandlerList = EventHandler[]
type EventHandlerMap = {
'*'?: EventHandlerList,
[type: string]: EventHandlerList
}
export default function Mitt(all: EventHandlerMap = {}) {
const WILD_CARD = '*'
const getListByType = (handlerMap: EventHandlerMap, eventType: string): EventHandlerList => {
handlerMap[eventType] = handlerMap[eventType] || []
return handlerMap[eventType]
}
const isEmptyHandlerList = (handlerList: EventHandlerList) => handlerList.length === 0
return {
on(type: string, handler: EventHandler) {
getListByType(all, type).push(handler)
},
off(type: string, handler: EventHandler) {
const eventList = all[type]
if (eventList) {
all[type] = eventList.filter(h => eventList.indexOf(h) < 0)
}
},
emit(type: string, evt: any) {
if (!isEmptyHandlerList(all[type])) {
getListByType(all, type).slice().forEach((handler: EventHandler) => handler({ event: evt }))
getListByType(all, WILD_CARD).slice().forEach((handler: EventHandler) => handler({ type, event: evt }))
}
}
}
}
const emitter = Mitt()
const fakeEventFunc = ({ event }: { event: any }) => {
console.log('Event Emitted!')
console.log('Let\'s make some changes');
return {
...event,
changes: 'awesome!'
}
}
const log = (eventName: string) => ({ event }: { event: any }) => console.log(eventName, event)
const fooLog = log('foo')
emitter.on('foo', fooLog)
emitter.on('*', ({ type, event }) => console.log(type, event))
emitter.on('bar', event => console.log(fakeEventFunc({ event })))
const testObj = { a: 'b' }
emitter.emit('foo', testObj)
emitter.emit('bar', testObj)
emitter.off('foo', fooLog)
emitter.off('bar', fakeEventFunc)
emitter.emit('foo', testObj)
emitter.emit('bar', testObj)
/*
Result
=======================================
foo { a: 'b' }
foo { a: 'b' }
Event Emitted!
Let's make some changes
{ a: 'b', changes: 'awesome!' }
bar { a: 'b' }
*/
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment