Typescript 类型体操 —— EventEmitter

2,806 阅读1分钟

🤔️要求

要求实现一个 EventEmitter 类,该类中存在两个方法 on / emit。on(functionName, function) 方法可以订阅一个 functionName 的函数。emit(functionName, ...args) 方法可以调用 on 方法中注册的函数,获得对应的函数类型

  const eventEmitter = new EventEmitter();
  eventEmitter.on('sayHello', (name: string) => {
    console.log(name);
  })

  eventEmitter.on('sayAge', (age: number) => {
    console.log(name);
  })

  eventEmitter.emit('sayHello', 'test') // expect success
  eventEmitter.emit('hello', 'test') // expect error, 函数名没有被注册
  eventEmitter.emit('sayHello', 123) // expect error, sayHello 的参数类型为 string 
  eventEmitter.emit('sayHello', 'test', '124') // expect error, sayHello 的参数数量为1 

📖知识点

🔗知识链接

  1. 知识点: dependent type _ 01
  2. 知识点: dependent type _ 02

😢问题 & 解答

  1. 题目链接:EventEmitter
  2. 解答

🍗场景

// 实现一个 eventEmitter 类

class EventEmitter<T extends Record<string, unknown[]>> {
  private fnMap = new Map<keyof T, (...args: any) => void>();
  on<K extends keyof T>(key: K, fn: (...args: T[K]) => void): void {
    this.fnMap.set(key, fn);
  }

  emit<K extends keyof T>(key: K): (...args: T[K]) => void {
    const fn = this.fnMap.get(key);
    return (...args: T[K]) => {
      fn && fn(...args);
    };
  }
}

const eventEmitter = new EventEmitter<{
    sayName: [string],
    sayAge: [number],
}>();

eventEmitter.on('sayName', (name: string) => {
    console.log(name)
});

eventEmitter.emit('sayName')('name');

eventEmitter.on('sayAge', (age: number) => {
    console.log(age)
});

eventEmitter.emit('sayAge')(88);