如何根据事件名称缩小回调事件类型
How to narrow callback event type based on event name
我正在尝试实现一个事件发射器。代码很简单
现在 tsc
认为 eventHandler
中的事件类型是 'ErrorEvent' | 'MessageEvent'
。
这就是问题所在,我希望 tsc
将类型缩小为正确的类型(取决于传递给 on
函数的 eventName
)。
能做到吗?
定义
interface Event {
code: string;
}
interface ErrorEvent extends Event {
xxx: number;
}
interface MessageEvent extends Event {
yyy: number;
}
interface Events {
error: ErrorEvent,
message: MessageEvent
}
type EventHandler = (event: Events[keyof Events]) => void;
TS代码
function on (eventName: keyof Events, eventHandler: EventHandler) {
console.log(eventName)
}
on('message', (event) => { // ErrorEvent | MessageEvent
console.log(event)
console.log(event.code)
console.log(event.xxx) // Property 'xxx' does not exist on type 'ErrorEvent | MessageEvent'.
console.log(event.yyy) // Property 'yyy' does not exist on type 'ErrorEvent | MessageEvent'.
})
首先你必须摆脱作为联合类型的 EventHandler:
type EventHandler<K extends EventKeys> = (event: Events[K]) => void
这样你就可以为每个具体 K
的处理程序获得一个具体类型。
然后确保 on
函数的第二个参数类型取决于第一个。因此,您必须向函数引入一个类型参数以获取行中的类型:
function on <K extends EventKeys>(eventName: K, eventHandler: EventHandler<K>): void {}
我认为应该这样做:
interface Event {
code: string;
}
interface ErrorEvent extends Event {
xxx: number;
}
interface MessageEvent extends Event {
yyy: number;
}
interface Events {
error: ErrorEvent,
message: MessageEvent
}
type EventKeys = keyof Events
type EventHandler<K extends EventKeys> = (event: Events[K]) => void;
function on <K extends EventKeys>(eventName: K, eventHandler: EventHandler<K>): void {
console.log(eventName)
}
on('message', (event) => {
console.log(event)
console.log(event.code)
console.log(event.xxx) // Property 'xxx' does not exist on type 'MessageEvent<any>'.
console.log(event.yyy)
})
我正在尝试实现一个事件发射器。代码很简单
现在 tsc
认为 eventHandler
中的事件类型是 'ErrorEvent' | 'MessageEvent'
。
这就是问题所在,我希望 tsc
将类型缩小为正确的类型(取决于传递给 on
函数的 eventName
)。
能做到吗?
定义
interface Event {
code: string;
}
interface ErrorEvent extends Event {
xxx: number;
}
interface MessageEvent extends Event {
yyy: number;
}
interface Events {
error: ErrorEvent,
message: MessageEvent
}
type EventHandler = (event: Events[keyof Events]) => void;
TS代码
function on (eventName: keyof Events, eventHandler: EventHandler) {
console.log(eventName)
}
on('message', (event) => { // ErrorEvent | MessageEvent
console.log(event)
console.log(event.code)
console.log(event.xxx) // Property 'xxx' does not exist on type 'ErrorEvent | MessageEvent'.
console.log(event.yyy) // Property 'yyy' does not exist on type 'ErrorEvent | MessageEvent'.
})
首先你必须摆脱作为联合类型的 EventHandler:
type EventHandler<K extends EventKeys> = (event: Events[K]) => void
这样你就可以为每个具体 K
的处理程序获得一个具体类型。
然后确保 on
函数的第二个参数类型取决于第一个。因此,您必须向函数引入一个类型参数以获取行中的类型:
function on <K extends EventKeys>(eventName: K, eventHandler: EventHandler<K>): void {}
我认为应该这样做:
interface Event {
code: string;
}
interface ErrorEvent extends Event {
xxx: number;
}
interface MessageEvent extends Event {
yyy: number;
}
interface Events {
error: ErrorEvent,
message: MessageEvent
}
type EventKeys = keyof Events
type EventHandler<K extends EventKeys> = (event: Events[K]) => void;
function on <K extends EventKeys>(eventName: K, eventHandler: EventHandler<K>): void {
console.log(eventName)
}
on('message', (event) => {
console.log(event)
console.log(event.code)
console.log(event.xxx) // Property 'xxx' does not exist on type 'MessageEvent<any>'.
console.log(event.yyy)
})