export interface HandlerFuncTypeHash { [ eventName ] : ( ... args : any [ ] ) => any ; } export class Emitter < HandlerFuncs extends HandlerFuncTypeHash > { private handlers : { [ Prop in keyof HandlerFuncs ] ? : HandlerFuncs [ Prop ] [ ] ; } = { } ; private options : Partial < HandlerFuncs > ; private thisContext : any = null ; setThisContext ( thisContext ) { this . thisContext = thisContext ; } setOptions ( options ) { this . options = options ; } on < Prop extends keyof HandlerFuncs > ( type , handler ) { addToHash ( this . handlers , type , handler ) ; } off < Prop extends keyof HandlerFuncs > ( type , handler ? ) { removeFromHash ( this . handlers , type , handler ) ; } trigger < Prop extends keyof HandlerFuncs > ( type , ... args ) { let attachedHandlers = this . handlers [ type ] || [ ] ; let optionHandler = this . options && this . options [ type ] ; let handlers = [ ] . concat ( optionHandler || [ ] , attachedHandlers ) ; for ( let handler of handlers ) { handler . apply ( this . thisContext , args ) ; } } hasHandlers ( type ) { return Boolean ( ( this . handlers [ type ] && this . handlers [ type ] . length ) || ( this . options && this . options [ type ] ) ) ; } } function addToHash ( hash , type , handler ) { ( hash [ type ] || ( hash [ type ] = [ ] ) ) . push ( handler ) ; } function removeFromHash ( hash , type , handler ? ) { if ( handler ) { if ( hash [ type ] ) { hash [ type ] = hash [ type ] . filter ( ( func ) => func !== handler ) ; } } else { delete hash [ type ] ; } }