Node.js 在扩展EventEmitter的TypeScript类中声明事件
我有一个扩展了Node.js 在扩展EventEmitter的TypeScript类中声明事件,node.js,typescript,Node.js,Typescript,我有一个扩展了EventEmitter的类,它可以发出eventhello。如何使用特定的事件名称和侦听器签名在方法上声明 class MyClass extends events.EventEmitter { emitHello(name: string): void { this.emit('hello', name); } // compile error on below line on(event: 'hello', listener: (name: str
EventEmitter
的类,它可以发出eventhello
。如何使用特定的事件名称和侦听器签名在方法上声明
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;
}
最有用的方法是使用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);
}
}
请注意,如果要导出类,接口和类都必须使用export
关键字声明。以下是我能够理解的。用泛型覆盖默认函数
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!
接口{
连接:()=>void
测试:(属性:字符串)=>void
}
类MyClass扩展了events.EventEmitter{
private\u untypedOn=this.on
private _untypedEmit=this.emit
public on=(事件:K,侦听器:IEmissions[K]):this=>this.\u untypedOn(事件,侦听器)
public emit=(事件:K,…args:Parameters):布尔=>this.\u untypedEmit(事件,…args)
this.emit('test','Testing')//这将为您键入!
}
//例如:
const inst=新的MyClass()
inst.on('test',info=>console.log(info))//这将被键入!
您可以使用它
例如:
从'tsee'导入{EventEmitter};
const events=new EventEmitter void,
}>();
//foo的参数是完全类型检查的
emit('foo',123,'helloworld');
该软件包还提供接口和一些UTIL。扩展@SergeyK的答案,使用它,您可以在emit
和函数上进行类型检查和完成,而无需重复事件类型
为每个事件类型定义事件侦听器签名:
声明接口,该接口基于EventListeners(MyClassEvents
)函数签名为MyClass
构造类型:
现在,您将在
和
emit函数上进行类型检查:
不幸的是,您只能在这两个函数上进行完成和类型检查(除非在MyClass接口中定义更多函数)
要获得更通用的解决方案,可以使用。
注意:它不会增加运行时开销
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();
}
}
从“微型发射器”导入{TypedEmitter};
接口MyClassEvents{
'add':(el:string,wasNew:boolean)=>void;
'delete':(changedCount:number)=>void;
}
类MyClass扩展了TypeDemiter{
构造函数(){
超级();
}
}
发生了什么错误?而且您的on
方法似乎缺少主体。正如@NitzanTomer所说,要么您的on
方法缺少主体,要么您希望将事件
参数声明为'hello'
以外的其他类型。应该对你有帮助。只需将更新1作为答案,因为另一种方式更麻烦。这太棒了,我喜欢你的软件包!那个包裹真是太棒了。到目前为止,这是我见过的最人性化的解决方案。谢谢大家!@MaxTruxa很高兴您发现它很有用:)这正是我所需要的。这样就可以在仍然强制键入的情况下重写函数。
interface MyClassEvents {
'add': (el: string, wasNew: boolean) => void;
'delete': (changedCount: number) => void;
}
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;
}
class MyClass extends EventEmitter {
constructor() {
super();
}
}
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();
}
}