【发布时间】:2022-01-25 18:22:09
【问题描述】:
我正在尝试在 TypeScript 中实现可扩展的 EventEmitter 模式。
这是它应该使用的方式:
class DataEmitter<T, _EE extends Dict<any[]>> extends EventEmitter<DefaultMerge<_EE, { data: [T] }>> {
// ...
}
因此,任何扩展 DataEmitter 的类都可能传递另一个对象类型,定义它能够发出的新事件,依此类推。
这就是我试图定义它的方式:
type Listener<T extends any[]> = (...args: T) => void
type Dict<V> = {
[name: string]: V
}
type DefaultMerge<A, B> = A & B
type EventEmitter_EE<_EE extends Dict<any[]> = {}> = DefaultMerge<
_EE,
{
listen: [{ event: 'listen' | keyof _EE }]
}
>
interface EE<_EE extends Dict<any[]> = {}> {
addListener<K extends keyof _EE>(
event: K,
listener: Listener<_EE[K]>
): void
emit<K extends keyof _EE>(event: K, ...args: _EE[K]): void
}
class EventEmitter<_EE extends Dict<any[]> = {}>
implements EE<EventEmitter_EE<_EE>>
{
private __listeners: {
[K in keyof EventEmitter_EE<_EE>]?: Listener<EventEmitter_EE<_EE>[K]>[]
} = {}
addListener<K extends keyof EventEmitter_EE<_EE>>(
event: K,
listener: Listener<EventEmitter_EE<_EE>[K]>
): void {
this.__listeners[event] = this.__listeners[event] || []
this.__listeners[event].push(listener)
// >> TypeScript Error << \\
this.emit('listen', { event })
}
emit<K extends keyof EventEmitter_EE<_EE>>(
event: K,
...args: EventEmitter_EE<_EE>[K]
): void {
const listeners = [...(this.__listeners[event] || [])]
for (const listener of listeners) {
listener.call(this, ...args)
}
}
}
注意EventEmitter 类带有一个名为"listen" 的默认事件。
但是,TypeScript 抱怨引用的行并显示以下错误消息:
Argument of type '[{ event: K; }]' is not assignable to parameter of type
'_EE["listen"] & [{ event: "listen" | keyof _EE; }]'.
Type '[{ event: K; }]' is not assignable to type '_EE["listen"]'.
理想情况下,它应该理解"listen" 是EventEmitter 的默认事件,并根据定义推断其类型为"listen" | keyof _EE。
我的猜测是DefaultMerge<A, B> 定义不明确;它应该返回一个“首先查看 B,然后,如果未定义,则查看 A”的对象类型。
如何摆脱这个错误?
【问题讨论】:
标签: typescript typescript-generics