在扩展 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
Declaring events in a TypeScript class which extends EventEmitter
提问by aleung
I have a class extends EventEmitter
that can emit event hello
. How can I declare the on
method 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 export
keyword.
请注意,如果你正在导出类,两者的接口和类必须与声明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 emit
and on
functions without repeating event types.
扩展@SergeyK 的答案,这样您就可以在不重复事件类型的情况下对函数emit
和on
函数进行类型检查和完成。
- Define event listener signatures for each event type:
- 为每个事件类型定义事件侦听器签名:
interface MyClassEvents {
'add': (el: string, wasNew: boolean) => void;
'delete': (changedCount: number) => void;
}
- Declare interface which constructs types for
MyClass
, based on EventListeners (MyClassEvents
) function signature:
- 声明为 构造类型的接口
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;
}
- Simply define you class extending
EventEmitter
:
- 简单地定义你的类扩展
EventEmitter
:
class MyClass extends EventEmitter {
constructor() {
super();
}
}
Now you will get type checking for on
and emit
functions:
现在您将获得类型检查on
和emit
功能:
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);
}
}