typescript之泛型的高级使用 - 给函数声明参数和返回值

背景和问题描述

先描述一下背景,简化一下问题

有一个 事件注册函数 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;

你可能感兴趣的:(typescript,javascript,开发语言)