打字稿类型和 .bind

Ste*_*r16 8 javascript events typescript

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

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));
  }
}
Run Code Online (Sandbox Code Playgroud)

我像这样创建我的事件 onPageSizeSelected = new EventType<PageSizeSelector>();

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

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

打字稿无法正确推断方法签名的绑定是什么?如何安全地保留this我的事件并强类型化我的事件?

jca*_*alz 5

不幸的是,TypeScript 在this自动检查上下文方面做得并不好。有建议添加类似--strictThis编译器选项的内容,以防止您传递错误绑定的函数,但尚未实现,显然是因为它会破坏大量现有代码并对编译器性能产生重大影响。如果你想看到实现,你可能想要去那个 GitHub 问题并给出一个和/或描述你的用例(如果它特别引人注目并且尚未在该问题中提到)。

如果您真的想让编译器执行此检查,这可能的,但是您需要手动将this参数添加到代码中的各种位置。例如(这里有一个最小的、完整的和可验证的例子,你的定义PageSizeSelectedHandler会派上用场),你可以做这样的事情:

// 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!
Run Code Online (Sandbox Code Playgroud)

所以编译器可以强制执行这些东西,但不能自动执行。不幸的是,这是我现在可以给出的最佳答案,直到并且除非--strictThis成为一件事。

希望有帮助。祝你好运!

  • @jcalz typescript 3.2 中的新 strictBindCallApply 是否为您解决了这个问题?刚刚安装,IDE 能够识别我的绑定方法何时具有不正确的参数类型。 (2认同)