我将一些JavaScript代码转换为TypeScript,但我无法弄清楚jQuery EventHandler的签名应该如何。
这是我在JavaScript中所拥有的,但简化为更通用的术语(我使用通过元素分发的自定义事件的某种pub-sub或observable模式):
Observer.prototype._subscribe = function() {
this._row.bind('onItemChanged', this, this._onChangedHandler);
};
Observer.prototype._onChangedHandler= function(event, someString, someObject) {
var that = event.data;
if (someString === '42') {
that.coolMethod(someObject);
} else if (someString === '69') {
that.otherCoolMethod(someObject);
}
};
在另一个原型中,我会调用trigger来通知观察者事件和至少2个数据参数(someString和someObject):
Subject.prototype.foo = function() {
// Trigger the event so Observer will be notified and pass in the string and the object (or any data whatsoever)
this._element.trigger("onItemChanged", ["42", this._data]);
};
现在我很难用TypeScript写这个,但这就是我认为它应该像:
export class Observer {
private _subscribe (): void {
this._element.bind('onItemChanged', this, this._onChangedHandler);
}
private _onChangedHandler(event: JQueryEventObject, someString: string, someObject: FooBarClass) {
let that = event.data as Observer;
if (someString === '42') {
that.coolMethod(someObject);
} else if (someString === '69') {
that.otherCoolMethod(someObject);
}
}
}
此TypeScript无法编译,但会出现以下错误:
类型'的参数(事件:JQueryEventObject,someString:string,someObject:FooBarClass)=>空隙'不能分配给' EventHandler |类型的参数EventHandlerBase>&#39 ;. 键入'(事件:JQueryEventObject,someString:string,someObject:FooBarClass)=>空隙'不能分配到' EventHandlerBase>'。 参数类型'事件'并且' t'是不相容的。 输入'事件'不能分配给' JQueryEventObject'。
那么事件处理程序的签名(参数类型)应该如何?
P.S。如果你愿意,你可以使用jQuery :: on()而不是jQuery :: bind();
重写P.P.S。我对如何获得正确的'这个'不感兴趣。除非我在这里走错路。
编辑(首次重播后): 正如建议的那样,我重写了我的TypeScript以使我的问题更加清晰。我知道使用胖箭符号来获得正确的'这个'但就像我之前说的那样,我对此并不感兴趣。我希望我的方法是类型安全的,所以我的处理程序方法的签名应该如何? 这确实有效:
private _subscribe (): void {
this._element.on('onItemChanged', () => this._onChangedHandler);
}
private _onChangedHandler(event: JQueryEventObject, someString: string, someObject: FooBarClass) {
}
但后来我预计这也应该有效:
private _subscribe(): void {
this._element.on('onItemChanged', (event: JQueryEventObject, someString: string, someObject: FooBarClass) => { this._onChangedHandler(event, someString, someObject); });
}
但我仍然无法获得第一个参数的正确事件类型来获得类型安全。随着'任何'键入它编译:
private _subscribe(): void {
this._element.on('onItemChanged', (event: any, someString: string, someObject: FooBarClass) => { this._onChangedHandler(event, someString, someObject); });
}
答案 0 :(得分:1)
P.P.S。我对如何获得正确的各种方法不感兴趣 '这个',除非我真的在错误的道路上。
我知道你不想听到这个,但是当你处理事件时,你确实需要照顾你的范围。
this._element.bind('onItemChanged', this, () => {
this._onChangedHandler();
});
我还建议移至on
,因为bind
已被弃用。
这感觉就像一个奇怪的答案,因为我认为你已经怀疑这两个了吗?
答案 1 :(得分:1)
通过添加'任何'在调试器中输入并运行我终于在运行时发现第一个参数是' JQuery.Event'在使用jQuery的类型定义时,也可以在TypeScript中正确编译的类型。太糟糕的tsc在编译时不能告诉我这个(或者我误解了问题中的错误显示)。 所以它应该是这样的(无论使用bind,fat arrow还是你自己的方式来保留正确的上下文/):
export class Observer {
private _element: JQuery;
private _subscribe(): void {
this._element.on('onItemChanged', (event: JQuery.Event, someString: string, someObject: FooBarClass) => { this._onChangedHandler(event, someString, someObject); });
}
private _onChangedHandler(event: JQuery.Event, someString: string, someObject: FooBarClass): void {
}
}
虽然这会编译并提供某种类型的安全性,但我有点失望,因为我可以使用错误的签名附加处理程序并且它仍然可以编译。我想这就是附加事件处理程序的工作方式。至少你可以直接使用typesafety调用你的方法,并仍然使用它们作为处理程序。
因此对于遇到此问题的其他人来说,签名应如下所示:
export class Observer {
private _element: JQuery;
private _subscribe(): void {
this._element.on('anyevent', () => this._yourOwnHandler);
}
private _yourOwnHandler(event: JQuery.Event, ...args: any[]): void {
}
}
' ... args'可以是任何你喜欢的东西,它可以为你提供你想要的参数的数量和类型。