如何为EventEmitter的eventPromise函数实现强类型返回值?
问题描述
我写了一个通用辅助函数eventPromise,用来通过await等待任意EventEmitter的事件触发,代码如下:
import { type EventEmitter } from 'eventemitter3' /** 返回一个在指定事件触发时resolve的Promise */ export const eventPromise = async (emitter: EventEmitter, event: string) => new Promise<any>(resolve => { emitter.once(event, d => resolve(d)) })
我使用eventemitter3提供的强类型事件定义:
type TestEvents = { foo: (payload: { bar: string }) => void } class TestEmitter extends EventEmitter<TestEvents> { test() { this.emit('foo', { bar: 'pizza' }) } }
但尝试获取强类型返回值时出现错误:Property 'bar' does not exist on type 'unknown'。我试了下面的泛型写法,但返回类型还是unknown:
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>) }) }
我希望这个函数能通用适配任意EventEmitter,而不只是TestEvents,请问问题出在哪?
问题原因与修复方案
核心问题
你未正确导入eventemitter3提供的EventMap类型,且泛型约束写法存在问题,导致TypeScript无法正确推导事件参数类型。另外,不必要的类型断言也干扰了类型推导逻辑。
修复后的代码
import { type EventEmitter, type EventMap } from 'eventemitter3' export const eventPromise = async < T extends EventMap, K extends keyof T >( emitter: EventEmitter<T>, event: K ): Promise<Parameters<T[K]>[0] | undefined> => { return new Promise((resolve) => { emitter.once(event, (...args) => { // 取第一个参数作为Promise的resolve值,同时适配无参数事件场景 resolve(args[0]) }) }) }
关键修改点
- 显式导入
EventMap:之前代码使用T extends EventMap但未导入该类型,TypeScript会将其识别为unknown,直接导致类型推导失败。 - 简化泛型约束:用
K extends keyof T替代EventEmitter.EventNames<T>,更贴合TypeScript原生类型推导逻辑,避免额外的类型解析歧义。 - 兼容无参数事件:将返回类型设为
Parameters<T[K]>[0] | undefined,避免事件无参数时出现类型报错。 - 移除冗余类型断言:直接通过
(...args)接收事件参数,无需强制转换监听函数类型,让TypeScript自动完成类型推导。
使用验证
const emitter = new TestEmitter() // 现在可正确推导返回值类型为{ bar: string } const data = await eventPromise(emitter, 'foo') console.log(data.bar) // 不再出现类型错误
内容的提问来源于stack exchange,提问作者Herb Caudill
相关产品推荐
相关产品推荐

