type Callback1 < T1 > = ( arg1 : T1 ) => any ; type Callback2 < T1 , T2 > = ( arg1 : T1 , arg2 : T2 ) => any ; type Callback3 < T1 , T2 , T3 > = ( arg1 : T1 , arg2 : T2 , arg3 : T3 ) => any ; type Callback4 < T1 , T2 , T3 , T4 > = ( arg1 : T1 , arg2 : T2 , arg3 : T3 , arg4 : T4 ) => any ; type Callback5 < T1 , T2 , T3 , T4 , T5 > = ( arg1 : T1 , arg2 : T2 , arg3 : T3 , arg4 : T4 , arg5 : T5 ) => any ; type Callback6Rest < T1 , T2 , T3 , T4 , T5 , T6 > = ( arg1 : T1 , arg2 : T2 , arg3 : T3 , arg4 : T4 , arg5 : T5 , arg6 : T6 , ... rest : any [ ] ) => any ; export class Events { private callbacks ? : Record < string , unknown > ; static eventSplitter = /\s+/ ; constructor ( opts ? ) { if ( typeof opts !== 'undefined' && opts . callbacks ) { this . callbacks = opts . callbacks ; } else { this . callbacks = { } ; } } on < T > ( event , callback , context ) ; on < T1 , T2 > ( event , callback , context ) ; on < T1 , T2 , T3 > ( event , callback , context ) ; on < T1 , T2 , T3 , T4 > ( event , callback , comtext ) ; on < T1 , T2 , T3 , T4 , T5 > ( event , callback , context ) ; on < T1 , T2 , T3 , T4 , T5 , T6 > ( event , callback , context ) ; on ( eventName , callback , context ) { let event , node , tail , list ; if ( ! callback ) { return this ; } eventName = eventName . split ( Events . eventSplitter ) ; const calls = this . callbacks || [ ] ; while ( ( event = eventName . shift ( ) ) ) { list = calls [ event ] ; node = list ? list . tail : { } ; node . next = tail = { } ; node . context = context ; node . callback = callback ; calls [ event ] = { tail , next : list ? list . next : node } ; } return this ; } once ( events , callback , context ) { const wrapper = ( ... args ) => { callback . apply ( this , args ) ; this . off ( events , wrapper , context ) ; } ; this . on ( events , wrapper , context ) ; return this ; } off ( events , callback , context ) { let event , calls , node , tail , cb , ctx ; if ( ! ( calls = this . callbacks ) ) { return this ; } if ( ! ( events || callback || context ) ) { delete this . callbacks ; return this ; } events = events ? events . split ( Events . eventSplitter ) : Object . keys ( calls ) ; while ( ( event = events . shift ( ) ) ) { node = calls [ event ] ; delete calls [ event ] ; if ( ! node || ! ( callback || context ) ) { continue ; } tail = node . tail ; while ( ( node = node . next ) !== tail ) { cb = node . callback ; ctx = node . context ; if ( ( callback && cb !== callback ) || ( context && ctx !== context ) ) { this . on ( event , cb , ctx ) ; } } } return this ; } trigger ( event ) ; trigger < T1 > ( event , arg ) ; trigger < T1 , T2 > ( event , arg1 , arg2 ) ; trigger < T1 , T2 , T3 > ( event , arg1 , arg2 , arg3 ) ; trigger < T1 , T2 , T3 , T4 > ( event , arg1 , arg2 , arg3 , arg4 ) ; trigger < T1 , T2 , T3 , T4 , T5 > ( event , arg1 , arg2 , arg3 , arg4 , arg5 ) ; trigger < T1 , T2 , T3 , T4 , T5 , T6 > ( event , arg1 , arg2 , arg3 , arg4 , arg5 , arg6 , ... rest ) ; trigger ( events ) { let event , node , calls , tail ; if ( ! ( calls = this . callbacks ) ) { return this ; } events = events . split ( Events . eventSplitter ) ; const rest = [ ] . slice . call ( arguments , 1 ) ; while ( ( event = events . shift ( ) ) ) { if ( ( node = calls [ event ] ) ) { tail = node . tail ; while ( ( node = node . next ) !== tail ) { node . callback . apply ( node . context || this , rest ) ; } } } return this ; } } export const eventCenter = new Events ( ) ;