javascript - typescript 类型和 .bind

标签 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) .它立即发现方法签名不正确并且参数过多。

typescript 无法正确推断方法签名的绑定(bind)是什么?我怎样才能安全地保存我的this并且我的事件是强类型的吗?

最佳答案

如果您只想让编译器捕获具有错误参数数量的绑定(bind)方法,并且您不关心 this上下文,您只需确保启用 the --strictBindCallApply compiler option :

class StringListeningClassThing {
  myString = "hey";
  oneParam(x: string) {
    return x + this.myString;
  }
  twoParams(x: number, y: string) {
    return x.toFixed(2) + y + this.myString;
  }
}

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

onPageSizeSelected.Attach(
  stringListenerThingy.twoParams); // error
onPageSizeSelected.Attach(
  stringListenerThingy.twoParams.bind(stringListenerThingy)); // error
onPageSizeSelected.Attach(
  stringListenerThingy.oneParam.bind(stringListenerThingy)); // okay
onPageSizeSelected.Attach(
  stringListenerThingy.twoParams.bind(stringListenerThingy, 2)); // okay
这可能就是您所需要的。但是这里仍然存在一些类型安全问题:

不幸的是,TypeScript 在类型检查方面做得不好this自动上下文:
onPageSizeSelected.Attach(
  stringListenerThingy.oneParam); // no error 
onPageSizeSelected.Attach(
  stringListenerThingy.oneParam.bind({ notGood: true })); // no error
这些被接受的事实意味着您将遇到运行时错误,如 stringListenerThingy的方法取消引用一个坏的 this .
microsoft/TypeScript#7968有建议添加类似 --strictThis 的内容编译器选项可以防止您传递错误绑定(bind)的函数,但它尚未实现,显然是因为它会 both break lots of existing code and have a significant compiler performance impact .如果你想看到实现,你可能想去那个问题并给它一个👍和/或描述你的用例(如果它特别引人注目并且在那个问题中没有提到)。
如果你真的想让编译器做这个检查,这是可能的,但你需要添加 this parameters手动到代码中的各种位置。例如,您可以执行以下操作:
// 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";
  oneParam(this: StringListeningClassThing, x: string) {
    return x + this.myString;
  }
  twoParams(this: StringListeningClassThing, x: number, y: string) {
    return x.toFixed(2) + y + this.myString;
  }
}
现在上面的例子给出了期望的错误:
// enjoy type safety   
onPageSizeSelected.Attach(
  stringListenerThingy.oneParam); // error 
onPageSizeSelected.Attach(
  stringListenerThingy.oneParam.bind({ notGood: true })); // error
所以编译器可以强制执行这些东西,但不能自动执行,除非--strictThis变成一个东西。
Playground link to code

关于javascript - typescript 类型和 .bind,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54710927/

相关文章:

multithreading - 在阻塞主线程中使用 TEvent 和 MsgWaitForMultipleObjects

javascript - jQuery事件是否阻塞

c# - 控制应用程序流程的问题

javascript - 使用 Object.keys() 获取 searchParams

javascript - 原型(prototype)继承 - 为什么这行不通?

javascript - 检查嵌套对象是否已声明并具有值而无需这么多条件检查

javascript - 在数组映射期间与 toLowerCase 和 indexOf 组合的可选链接

javascript - 如何通过使用 takeUntil 的多个条件来停止订阅

typescript - 将扩展类型 Prop 传播到 Typescript 接口(interface)中

Angular Chrome Api 数据绑定(bind)不起作用