【发布时间】:2020-06-30 03:13:56
【问题描述】:
我在 typescript 中有一个自定义事件发射器系统,但我只能使用 1 个参数,有代码:
type EventMap = Record<string, any>;
type EventKey<T extends EventMap> = string & keyof T;
type EventReceiver<T> = (params: T) => void;
interface IEmitter<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;
}
class EventHandler<T extends EventMap> implements IEmitter<T> {
private emitter: EventEmitter = new EventEmitter();
on<K extends EventKey<T>>(eventName: K, fn: EventReceiver<T[K]>): void {
this.emitter.on(eventName, fn);
}
off<K extends EventKey<T>>(eventName: K, fn: EventReceiver<T[K]>): void {
this.emitter.off(eventName, fn);
}
emit<K extends EventKey<T>>(eventName: K, params: T[K]): void {
this.emitter.emit(eventName, params);
}
}
const handler = new EventHandler<{
foo: string,
bar: number
multiple: [ string, number ]
}>();
handler.emit('foo', 'baz');
handler.emit('multiple', 'aaa', 10);
handler.on('foo', (param) => console.log(param)); // baz
handler.on('multiple', (param) => console.log(param)); // [ 'aaa', 10 ] => This is not what I want
您可以看到multiple 事件为on 方法提供一个参数,该参数是一个包含两个值的数组。
但是我希望能够做到这一点:
handler.on('multiple', (aaa, ten) => console.log(`${aaa} , ${ten}`)); // aaa , 10
如何修改代码才能做到这一点?
【问题讨论】:
-
重构一切以使用元组代替?
type EventReceiver<T extends readonly any[]> = (...params: T) => void;然后{foo: [string], bar: [number], multiple: [string, number]}? -
或使
EventReceiver复杂化以检测数组类型,但这可能会做您不想要的事情并且可能很脆弱:type EventReceiver<T> = (...params: T extends readonly any[] ? T : [T]) => void -
在 4.0 中也可以使用命名元组:
multiple: [strarg: string, nrArgs: number] -
如果你想把这些想法写成答案,请告诉我,祝你好运
-
是
import {EventEmitter} from 'events';,events是一个节点模块。
标签: typescript types eventemitter