背景和问题描述
先描述一下背景,简化一下问题
有一个 事件注册函数 on 和 触发函数 emit
function on(name: string, listener: (data?: any));
function emit(name: string, data?: any);
其中name 和 data 参数是一一对应的,
现在有以下 name - data type的map
interface EventMap{
event1: {e1: string};
event2: {e2: number};
}
现在希望 声明一下 on和emit 方法,使ts能够准确的进行报错和类型判断,希望达到的效果如下
emit('event1', {}); // 报错
emit('event2', {}); // 报错
emit('event3', {}); // 不报错,自定义事件
on('event1', (d)=>{}) // d 类型为 {e1: string}
on('event2', (d)=>{}) // d 类型为 {e2: number}
on('event3', (d)=>{}) // d 类型为 any
解决方案
这里我们通过泛型 + keyof + 查找类型 来实现,先上实现代码
interface EventMap {
event1: {e1: string};
event2: {e2: number};
[prop: string]: any; // 用来支持自定义事件
}
export type EventRegister =
<Key extends keyof EventMap>(name: Key, listener: (data: IMap[Key])=>void) => void;
export type EventEmitter =
<Key extends keyof EventMap>(name: Key | string, data?: IMap[Key]) => void;
使用:
const on: EventRegister = (name, listener) => {
};
const emit: EventEmitter = (name, data) => {
};
讲解一下这一句,首先通过函数前置泛型声明了一个 Key 继承map的键,然后在函数参数定义中声明name为map的键,listener 参数data声明为 map对应的值类型
export type EventRegister =
<Key extends keyof EventMap>(name: Key, listener: (data: IMap[Key])=>void) => void;