type Callback = (event: TopicEvent) => void; type Listeners = { [type: string]: Callback[]; }; export type TopicEvent = { type: string; defaultPrevented?: boolean; }; export class EventTopic { private listeners: Listeners; constructor() { this.listeners = {}; } addEventListener(type: string, callback: Callback) { if (!(type in this.listeners)) { this.listeners[type] = []; } this.listeners[type].push(callback); } removeEventListener(type: string, callback: Callback) { if (!(type in this.listeners)) { return; } var stack = this.listeners[type]; for (var i = 0, l = stack.length; i < l; i++) { if (stack[i] === callback) { stack.splice(i, 1); return; } } } dispatchEvent(event: TopicEvent) { if (!(event.type in this.listeners)) { return true; } var stack = this.listeners[event.type].slice(); for (var i = 0, l = stack.length; i < l; i++) { stack[i].call(this, event); } return !event.defaultPrevented; } }