我有一个辅助函数,可以让我在
await
上处理 EventEmitter
事件。
import { type EventEmitter } from 'eventemitter3'
/** Returns a promise that resolves when the given event fires */
export const eventPromise = async (emitter: EventEmitter, event: string) =>
new Promise<any>(resolve => {
emitter.once(event, d => resolve(d))
})
所以我可以等待下一个
foo
活动如下:
await eventPromise(someEmitter, 'foo')
到目前为止,效果很好。
我正在使用 eventemitter3,它为我提供了强类型事件:
type TestEvents = {
foo: (payload: { bar: string }) => void
}
class TestEmitter extends EventEmitter<TestEvents> {
test() {
this.emit('foo', { bar: 'pizza' })
}
}
所以看起来
eventPromise
的返回值应该可以是强类型的:
const testEmitter = new TestEmitter()
const { bar } = await eventPromise(testEmitter, 'foo')
但这给了我一个错误,
Property 'bar' does not exist on type 'unknown'
。 (参见这个游乐场。)
我绕了很多圈子,试图让
eventPromise
返回强类型值。这是我得到的最接近的:
export const eventPromise = async <
T extends EventMap,
K extends EventEmitter.EventNames<T> = EventEmitter.EventNames<T>,
>(
emitter: EventEmitter<T>,
event: K
) => {
return new Promise<Parameters<T[K]>[0]>(resolve => {
const listener = (payload: Parameters<T[K]>[0]) => resolve(payload)
emitter.once(event, listener as EventEmitter.EventListener<T, K>)
})
}
可以编译,但返回类型仍然是
unknown
。 (参见这个游乐场。)
老实说,我觉得这些体操都没有必要——原始函数不应该有足够的信息让 TypeScript 推断其返回类型吗?
我错过了什么?
我能够使用下面的代码使其工作。
为了方便,我提取了更多
TestMessages
的定义,与您所显示的代码的相关差异在eventPromise
,即:
eventPromise
可以进一步抽象,以便在输入中获取具有任意事件的发射器,因此它应该成为 generic,但是否需要这取决于具体要求。
import { EventEmitter } from 'eventemitter3'
type TestMessages = {
foo: { bar: string }
}
type TestEvents = {
foo: (payload: TestMessages["foo"]) => void
}
class TestEmitter extends EventEmitter<TestEvents> {
test() {
this.emit('foo', { bar: 'pizza' })
}
}
/** Returns a promise that resolves when the given event fires */
export const eventPromise = async (emitter: TestEmitter, event: keyof TestEvents) =>
new Promise<TestMessages[typeof event]>(resolve => {
return emitter.once(event, d => resolve(d))
});
const testEmitter = new TestEmitter();
const { bar } = await eventPromise(testEmitter, 'foo');