在扩展 EventEmitter 的 TypeScript 类中声明事件

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/39142858/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-21 03:47:50  来源:igfitidea点击:

Declaring events in a TypeScript class which extends EventEmitter

node.jstypescript

提问by aleung

I have a class extends EventEmitterthat can emit event hello. How can I declare the onmethod with specific event name and listener signature?

我有一个EventEmitter可以发出 event的类扩展hello。如何声明on具有特定事件名称和侦听器签名的方法?

class MyClass extends events.EventEmitter {

  emitHello(name: string): void {
    this.emit('hello', name);
  }

  // compile error on below line
  on(event: 'hello', listener: (name: string) => void): this;
}

回答by SergeyK

Most usable way of doing this, is to use declare:

最有用的方法是使用declare

declare interface MyClass {
    on(event: 'hello', listener: (name: string) => void): this;
    on(event: string, listener: Function): this;
}

class MyClass extends events.EventEmitter {
    emitHello(name: string): void {
        this.emit('hello', name);
    }
}

Note that if you are exportingyour class, boththe interface and class have to be declared with the exportkeyword.

请注意,如果你正在导出类,两者的接口和类必须与声明export的关键字。

回答by Morglod

You can use typed event emitter packagefor this.

您可以为此使用类型化事件发射器包

eg:

例如:

import { EventEmitter } from 'tsee';

const events = new EventEmitter<{
    foo: (a: number, b: string) => void,
}>();

// foo's arguments is fully type checked
events.emit('foo', 123, 'hello world');

This package also provide interfaces & some utils.

这个包还提供了接口和一些实用程序。

回答by Isaac Nassimi

Here's what I was able to figure out. Overriding the default function with a generic!

这是我能够弄清楚的。用泛型覆盖默认函数!

interface IEmissions {
  connect: () => void
  test: (property: string) => void
}

class MyClass extends events.EventEmitter {
  private _untypedOn = this.on
  private _untypedEmit = this.emit
  public on = <K extends keyof IEmissions>(event: K, listener: IEmissions[K]): this => this._untypedOn(event, listener)
  public emit = <K extends keyof IEmissions>(event: K, ...args: Parameters<IEmissions[K]>): boolean => this._untypedEmit(event, ...args)

  this.emit('test', 'Testing') // This will be typed for you!
}

// Example:
const inst = new MyClass()
inst.on('test', info => console.log(info)) // This will be typed!

回答by binier

to extend @SergeyK's answer, with this you can get type-checking and completion on both emitand onfunctions without repeating event types.

扩展@SergeyK 的答案,这样您就可以在不重复事件类型的情况下对函数emiton函数进行类型检查和完成。

  1. Define event listener signatures for each event type:
  1. 为每个事件类型定义事件侦听器签名:
interface MyClassEvents {
  'add': (el: string, wasNew: boolean) => void;
  'delete': (changedCount: number) => void;
}
  1. Declare interface which constructs types for MyClass, based on EventListeners (MyClassEvents) function signature:
  1. 声明为 构造类型的接口MyClass,基于 EventListeners( MyClassEvents) 函数签名:
declare interface MyClass {
  on<U extends keyof MyClassEvents>(
    event: U, listener: MyClassEvents[U]
  ): this;

  emit<U extends keyof MyClassEvents>(
    event: U, ...args: Parameters<MyClassEvents[U]>
  ): boolean;
}
  1. Simply define you class extending EventEmitter:
  1. 简单地定义你的类扩展EventEmitter
class MyClass extends EventEmitter {
  constructor() {
    super();
  }
}


Now you will get type checking for onand emitfunctions:

现在您将获得类型检查onemit功能:

enter image description here

enter image description here

enter image description here

enter image description here

Unfortunately you will get completion and type-checking only on those two functions (unless you define more functions inside MyClass interface).

不幸的是,您只能对这两个函数进行补全和类型检查(除非您在 MyClass 接口中定义更多函数)。

To get more generic solution, you can use this package. note:it adds no runtime overhead.

要获得更通用的解决方案,您可以使用此包注意:它不会增加运行时开销。

import { TypedEmitter } from 'tiny-typed-emitter';

interface MyClassEvents {
  'add': (el: string, wasNew: boolean) => void;
  'delete': (changedCount: number) => void;
}

class MyClass extends TypedEmitter<MyClassEvents> {
  constructor() {
    super();
  }
}

回答by basarat

Simply wire it yourself to on('hello'e.g.:

只需将它自己连接到on('hello'例如:

class MyClass extends events.EventEmitter {

  emitHello(name: string): void {
    this.emit('hello', name);
  }

  on(listener: (name: string) => void){
    return this.on('hello',listener);
  } 
}