如何在TypeScript

时间:2017-09-28 18:17:51

标签: javascript jquery typescript

我将一些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); });
}

2 个答案:

答案 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'可以是任何你喜欢的东西,它可以为你提供你想要的参数的数量和类型。