Skip to content

Instantly share code, notes, and snippets.

@SuperOleg39
Created May 22, 2019 10:31
Show Gist options
  • Select an option

  • Save SuperOleg39/cfcac611d1002bcae7baa0f02120c1c7 to your computer and use it in GitHub Desktop.

Select an option

Save SuperOleg39/cfcac611d1002bcae7baa0f02120c1c7 to your computer and use it in GitHub Desktop.
type BaseEventsMap = {
[key: string]: any[]; // ключ - название события, значение - возможные аргументы
};
type Callback<P extends any[]> = (...payload: P) => void;
class EventEmitter<EventsMap extends BaseEventsMap> {
events: Map<keyof EventsMap, Set<Callback<EventsMap[keyof EventsMap]>>> = new Map();
on<E extends keyof EventsMap>(event: E, callback: Callback<EventsMap[E]>): Function {
if (!this.events.has(event)) {
this.events.set(event, new Set());
}
const subscribers = this.events.get(event);
subscribers.add(callback);
return () => subscribers.delete(callback);
}
off<E extends keyof EventsMap>(event: E, callback: Callback<EventsMap[E]>) {
if (!this.events.has(event)) {
return;
}
this.events.get(event).delete(callback);
}
emit<E extends keyof EventsMap>(event: E, ...payload: EventsMap[E]) {
if (!this.events.has(event)) {
return;
}
this.events.get(event).forEach((callback) => {
callback(...payload);
});
}
}
type MyEventsMap = {
foo: [];
bar: [number];
};
const emitter = new EventEmitter<MyEventsMap>();
emitter.on('foo', () => {
});
emitter.on('bar', (a) => {
});
emitter.on('baz', (a) => {
});
emitter.emit('foo', '');
emitter.emit('bar', 1);
export { EventEmitter };
@SuperOleg39
Copy link
Copy Markdown
Author

type BaseEventsMap = {
    [key: string]: (...args: any[]) => void; // ключ - название события, значение - возможные аргументы
};

type Callback<P extends any[]> = (...payload: P) => void;

class EventEmitter<EventsMap extends BaseEventsMap> {
    events: Map<keyof EventsMap, Set<Callback<Parameters<EventsMap[keyof EventsMap]>>>> = new Map();

    on<E extends keyof EventsMap>(event: E, callback: Callback<Parameters<EventsMap[E]>>): Function {
        if (!this.events.has(event)) {
            this.events.set(event, new Set());
        }

        const subscribers = this.events.get(event);

        subscribers.add(callback);

        return () => subscribers.delete(callback);
    }

    off<E extends keyof EventsMap>(event: E, callback: Callback<Parameters<EventsMap[E]>>) {
        if (!this.events.has(event)) {
            return;
        }

        this.events.get(event).delete(callback);
    }

    emit<E extends keyof EventsMap>(event: E, ...payload: Parameters<EventsMap[E]>) {
        if (!this.events.has(event)) {
            return;
        }

        this.events.get(event).forEach((callback) => {
            callback(...payload);
        });
    }
}

type MyEventsMap = {
    foo: () => void;
    bar: (a: number, b: string) => void;
};

const emitter = new EventEmitter<MyEventsMap>();

const handler: MyEventsMap['bar'] = (a, b) => {
    console.log(a)
}

emitter.on('foo', () => {

});

emitter.on('bar', handler);

emitter.on('baz', (a) => {

});

emitter.emit('foo', '');

emitter.emit('bar', 1);

export { EventEmitter };

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment