typescript - 事件映射和类型保护
问题描述
假设我正在为聊天应用程序构建一个事件管理器。我之前使用过事件地图并且玩得很开心,所以我会再试一次。
这是活动地图:
interface ChatEventMap {
incomingMessage: string;
newUser: {
name: string;
id: number;
};
}
type EvType = keyof ChatEventMap;
type Ev<T extends EvType> = ChatEventMap[T];
因此,为了监听一个事件,我们有一个on
接收两个参数的函数:type
事件的(或名称),以及一个被称为传递事件数据的回调。
是这样的:
function on<T extends EvType>(type: T, callback: (data: Ev<T>) => void) {
// do stuff
}
on('newUser', user => {
console.log(user.name); // No errors!
});
但现在我需要一次收听所有事件。我想制作一个onEvent
只接收事件类型及其数据的回调的函数。
问题是在回调函数内部,类型保护不起作用!
function onEvent(callback: <T extends EvType>(
ev: { type: T; data: ChatEventMap[T] },
) => void) {
// do stuff
}
onEvent(ev => {
if (ev.type === 'newUser') {
console.log(ev.data.name); // Error: Property 'name' does not exist on type 'ChatEventMap[T]'
}
});
我究竟做错了什么?
解决方案
在这里你有工作代码
interface ChatEventMap {
incomingMessage: string;
newUser: {
id: number;
name: string;
};
}
type EvType = keyof ChatEventMap;
type Ev<T extends EvType> = ChatEventMap[T];
// a bit of love for TypeScript
type Mapped = {
[P in keyof ChatEventMap]: {
type: P, data: ChatEventMap[P]
}
}
function on<T extends EvType>(type: T, callback: (data: Ev<T>) => void) {
// do stuff
}
on('newUser', user => {
console.log(user.name); // No errors!
});
function onEvent(callback: (ev: Mapped[EvType]) => void) { }
onEvent(ev => {
if (ev.type === 'newUser') {
console.log(ev.data.name); // ok
}
if (ev.type === 'incomingMessage') {
console.log(ev.data); // ok, string
}
});
有时,泛型并不是最好的解决方案。
请记住,接下来的两个函数是不一样的:
function onEvent(callback: <T extends EvType>(ev: Mapped[T]) => void) { }
function onEvent(callback: (ev: Mapped[EvType]) => void) { }
推荐阅读
- sql - 如何返回嵌套的 JSON 数组
- angular - 在星云寄存器组件中添加自定义字段
- sas - SAS中的朴素贝叶斯分类器
- javascript - 使用 Highcharts 映射 json 数据的问题
- kubernetes - 在 Kubernetes 中应用更改的限制?
- javascript - Jquery Loop无限运行
- python - cv2.imwrite 和 pyplot.imshow 以不同方式显示灰度图像
- python - 熊猫读取谷歌表格数据类型错误
- javascript - Web Crawler with Scraper 使用 Puppeteer 和 Scrapy
- python - "with suppress" not working anymore in my Python 3 code?