Skip to main content

Event Emitters in TypeScript

· 2 min read
rjzaworski.com

Ref: Event Emitters in TypeScript

从UI交互到Node.js的核心事件循环, 基于事件循环是JavaScript开发的一部分.

TypeScript可以让事件驱动的程序显式声明什么事件会被触发。有大量TypeScript event handlers示例,不过自己也可以很容易实现一个。 关键点是使用一个已知的什么事件会触发的map作为Emitter

通常一个 event emitter 的TypeScript类型定义看起来像这样:

type EventMap = Record<string, any>;

type EventKey<T extends EventMap> = string & keyof T;
type EventReceiver<T> = (params: T) => void;

interface Emitter<T extends EventMap> {
on<K extends EventKey<T>>
(eventName: K, fn: EventReceiver<T[K]>): void;
off<K extends EventKey<T>>
(eventName: K, fn: EventReceiver<T[K]>): void;
emit<K extends EventKey<T>>
(eventName: K, params: T[K]): void;
}

接下来写一个实现 Emitter 的小例子 eventEmitter :

// `listeners` are unbounded -- don't use this in practice!
function eventEmitter<T extends EventMap>(): Emitter<T> {
const listeners: {
[K in keyof EventMap]?: Array<(p: EventMap[K]) => void>;
} = {};

return {
on(key, fn) {
listeners[key] = (listeners[key] || []).concat(fn);
},
off(key, fn) {
listeners[key] = (listeners[key] || []).filter(f => f !== fn);
},
emit(key, data) {
(listeners[key] || []).forEach(function(fn) {
fn(data);
});
},
};
}

当我们使用 eventEmitter 产生一个新的 emitter 时, 我们可以提供一个emitter将会触发的事件列表:

const emitter = eventEmitter<{
data: Buffer | string;
end: undefined;
}>();