打字稿类型和.bind

时间:2019-02-15 14:00:10

标签: javascript typescript events

我开始深入研究泛型,并拥有一个看起来像这样的泛型事件类

export interface Listener < T > {
  (event: T): any;
}

export class EventTyped < T > {
  //Array of listeners
  private listeners: Listener < T > [] = [];

  Attach(listener: Listener < T > ) {
    this.listeners.push(listener);
  }

  Emit(event: T) {
    this.listeners.forEach(listener => listener(event));
  }
}

我像这样onPageSizeSelected = new EventType<PageSizeSelector>();

创建我的活动

我的听众签名是这个PageSizeSelectedHandler(event:Event,object:PageSizeSelector)

当我附加这样的事件pageSizeSelector.onPageSizeSelected.Attach(this.PageSizeSelectedHandler.bind(this))时,不会引发任何错误。 当像这样pageSizeSelector.onPageSizeSelected.Attach(this.PageSizeSelectedHandler)附加处理程序时。它立即发现方法签名不正确并且参数太多。

做什么的打字稿不能正确地推断方法签名?如何安全地保存我的this并强行输入我的活动?

1 个答案:

答案 0 :(得分:2)

不幸的是,TypeScript在自动检查this上下文的类型方面做得不好。有suggestion添加了类似--strictThis的编译器选项,可以防止传递错误绑定的函数,但尚未实现,显然是因为它会both break lots of existing code and have a significant compiler performance impact 。如果您想看到已实现的实现,则可能需要转到that GitHub issue并给它一个和/或描述您的用例(如果它特别引人注目并且在该问题中未提及)。

如果您真的想让编译器进行此检查,则 是可能的,但是您需要手动将this parameters添加到代码中的所有位置。例如(在这里定义为PageSizeSelectedHandler的{​​{3}}会派上用场),您可以执行以下操作:

// explicitly add void this-context to definition of Listener
export interface Listener<T> {
  (this: void, event: T): any;
}

// explicitly add class-based this-context to all methods 
class StringListeningClassThing {
  myString = "hey";
  doSomething(this: StringListeningClassThing, x: string) {
    return x + this.myString;
  }
}

const onPageSizeSelected = new EventTyped<string>();
const stringListenerThingy = new StringListeningClassThing();

// enjoy type safety   
onPageSizeSelected.Attach(stringListenerThingy.doSomething); // error as desired
onPageSizeSelected.Attach(stringListenerThingy.doSomething.bind({notGood: true})); // also error
onPageSizeSelected.Attach(stringListenerThingy.doSomething.bind(stringListenerThingy)); // okay!

因此编译器可以强制执行此操作,但不能自动执行。不幸的是,这是我目前能给出的最好的答案,直到并且除非--strictThis成为事实。

希望有帮助。祝你好运!