我有一个可以发出事件EventEmitter
的类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;
}
答案 0 :(得分:22)
最有效的方法是使用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);
}
}
答案 1 :(得分:14)
扩展@SergeyK的答案,这样您就可以在emit
和on
函数上进行类型检查和完成,而无需重复事件类型。
interface MyClassEvents {
'add': (el: string, wasNew: boolean) => void;
'delete': (changedCount: number) => void;
}
MyClass
)函数签名为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;
}
EventEmitter
:class MyClass extends EventEmitter {
constructor() {
super();
}
}
现在,您将获得on
和emit
函数的类型检查:
不幸的是,您只能对这两个函数进行完成和类型检查(除非您在MyClass接口中定义了更多函数)。
要获取更多通用解决方案,可以使用this package。 注意:,它不会增加运行时开销。
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();
}
}
答案 2 :(得分:2)
只需将自己连接到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);
}
}
答案 3 :(得分:1)
您可以为此使用typed event emitter package。
例如:
<script>
function calculateDiff(){
var FromYear = parseInt(document.getElementById("FromYear").value);
var FromMonth = parseInt(document.getElementById("FromMonth").value);
var FromDay = parseInt(document.getElementById("FromDay").value);
//current date
var today = new Date();
var ToYear = today.getFullYear();
var ToMonth = today.getMonth() + 1;
var ToDay = today.getDay()
var years, months, days;
//months
months = ToMonth - FromMonth;
if(ToDay < FromDay) {
months = months -1;
}
//years
years = ToYear - FromYear;
if(ToMonth < FromMonth) {
years = years - 1;
months = months + 12;
}
//days
days = Math.floor(31 - (FromYear + years, FromMonth + months - 1, FromDay));
//answer order
var answer = years + " years, " + months + " months, and " + days + " days.";
//post answer
document.getElementById("result").textContent = answer;
return {years: years, months: months, days: days};
}
</script>
<table>
<tbody>
<tr class="header">
<th> </th>
<th>Year</th>
<th>Month</th>
<th>Day</th>
</tr>
<tr>
<th>Birth Date</th>
<td><input id="FromYear" placeholder="YYYY" value=""></td>
<td><input id="FromMonth" placeholder="MM" value=""></td>
<td><input id="FromDay" placeholder="DD" value=""></td>
</tr>
<tr>
<th colspan="4">
<button id="calculateDiff" onclick="calculateDiff()">Calculate</button>
</th>
</tr>
<tr colspan="4">
<th>You are <div id="result"></div></th>
</tr>
</tbody>
</table>
此软件包还提供了接口和一些实用程序。
答案 4 :(得分:0)
这就是我能够弄清楚的。用泛型覆盖默认功能!
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!
答案 5 :(得分:0)
对 the official typing package 使用 events library:
npm install events @types/events