Typescript 类型和 .bind

2024-03-30

我开始深入研究泛型并拥有一个如下所示的通用事件类

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

打字稿无法正确推断方法签名,bind 做了什么?我怎样才能安全地保管我的this我的事件是强类型的吗?


如果您想要的只是让编译器捕获参数数量错误的绑定方法,并且您不关心this上下文,您只需确保启用the --strictBindCallApply编译器选项 https://www.typescriptlang.org/docs/handbook/release-notes/typescript-3-2.html#strictbindcallapply:

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.

有一个建议位于微软/TypeScript#7968 https://github.com/Microsoft/TypeScript/issues/7968添加类似的东西--strictThis编译器选项将阻止您传递错误绑定的函数,但它尚未实现,显然是因为它会两者都会破坏大量现有代码并对编译器性能产生重大影响 https://github.com/Microsoft/TypeScript/issues/7689#issue-143586130。如果您想看到它的实现,您可能需要转到该问题并给它一个????和/或描述您的用例(如果它特别引人注目并且该问题中尚未提及)。

如果你真的想让编译器做这个检查,它is可能,但您需要添加this参数 https://www.typescriptlang.org/docs/handbook/2/classes.html#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

所以编译器can强制执行这些内容,但不会自动执行,直到并且除非--strictThis成为一件事。

Playground 代码链接 https://www.typescriptlang.org/play?ts=4.5.2#code/PTAEFMA8AcBsEsDG8AusCeoCGATHoA3Ae3nxQAt4BnURIgOxShQFgAoKaIgJxVHkbhuAMyyJwoADLUm9IQB4AKgD5QAb3ahQACgrUAXIRI4ANBALhGhxQEpDWeugDc7AL7t2nHn0SwsVGgBRC0ZFdGhwHCVVDTYtEABBbm4sTCJhUAQqWSEqTVBobngCLCZMmUtcw2lsyu5ogG0AXVAAXlBmlzZ8hJQUMXJtLJzuaoq5epUbdXytPSoAOmG6xegAVypB5YmbLq13brjQQIBbVG1wEJRraditOcpF7dyF4R5AgaHxoTbVZ+4LlcbLt8gcDuwQBAYAhkGhMLh8L5-FQALQAI38kVA8xRdEEkD4KCI2FgsFAJ3AFCIOBo7CRAVAAGUUEV6ABzGqyARsgDCfgCiko7JmRxO6GZrLZbVAACJyOB0DK9qAGOAAApYFInXSPQwS7mcyzcvnIwXcsyQQzZSW3WagbiUtbceigSCgADU2MeCzF+vZyoOcwA7kQNVqqDqDEyWQbxsb+VQzeyLYZ6GsTmihGZ0FaY+zbUctA6UE6XZAFkSAGLwSCRbQAJmmnswnvmPvFebZAbcHjYeOyKvoGrZ4EZ8AAXqPwLBwIgmPh2nIg8crmEIlFrdzlNoQX2GAPN+zDRMk2zMIvwMu-Ry4+yTQKhWyd10IWAUSjN3OAEICHA8rCkgk0BwJg8qwNANDyg67AMMOo4TlOM5zpECy9P0iCDIeN61Cej7oBWIZhlgJxULsoCQkI3A8NgNA4OAVDwA6OAwUOWAjmOk6MtOs7zqhfSfFhx5CKe+EoIRmrEYsaK-tognfNwInAk45FgJR1H+KAdEMUxLFwRxiE8ShaECZ2QkKXhCyqkRJwLNJ9A4LJpnyYpZGQkQADWqQAIS6Wx8GcdxyE4Hx6GYU5OHCRZYmhhJJG2TJckReZ3LoGYjauWAHmpL2FH0AAVkQmAoOEEhUFgwiUpgWi+exCFcUhvHGRh2j5IlIwiZZcjWRlEDJOptH0YxkQ1f5BlBSFnyteF7UWVZsXxfZ2hqKA9BECgADiRDUoYLJrBIrhKSpJJUMSancL2QA

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Typescript 类型和 .bind 的相关文章

  • Javascript JSON stringify 没有要包含在数据中的数字索引

    我正在尝试通过 JSON 传递非数字索引值 但没有获取数据 var ConditionArray new Array ConditionArray 0 1 ConditionArray 1 2 ConditionArray 2 3 Cond
  • Web SQL 将数据插入多行

    我尝试在 Web SQL 数据库中一次将变量插入多行 但使用我所知的所有方法时 我收到错误 INSERT INTO tab a b VALUES v1 v2 v3 v4 gt gt could not prepare statement 1
  • 使用 @Input() 时出现 TypeScript 错误

    我正在尝试使用 Angular 4 开发一个应用程序 但是我在使用时收到一条错误消息 Input inputProducts products Product 错误是 tslint 在 ProductListComponent 类中 指令输
  • 通过 HTML 将复杂变量传递给 javascript 的正确方法

    我试图摆脱使用 PHP 的 htmlentities 但我在这里停止了 但后来我想 我不做替换和检查特殊字符 而是只 JSON 整个对象 这提供了一个非常不受欢迎的结果 其中包含大量双引号 那么我应该怎么做呢 我应该为每个图像分配一个数字唯
  • NodeJS Express 中每个请求的全局范围

    我有一个基本的快速服务器 需要在每个请求处理期间存储一些全局变量 更深入地说 请求处理涉及许多需要存储在变量中的操作 例如global transaction 当然 如果我使用global范围 每个连接都将共享其事务的信息 并且我需要一个全
  • 降低 Nodejs 服务器上的 CPU 利用率

    我正在研究降低 CPU 利用率的有趣方法 在 NodeJS 服务器上 在我的研究过程中 我发现了以下文章 http engineering linkedin com nodejs blazing fast nodejs 10 perform
  • Firestore onSnapshot() 方法多次触发

    我有一个带有多个路由和 vuex 的 vue cli 4 应用程序 Firestore 数据库已成功连接 我的应用程序立即反映从 Firestore 控制台应用于数据库的修改 在离开包含与 Firestore 同步 的组件的路线然后返回后
  • Ionic 和 Angular 2 - 拒绝应用“http://localhost:8100/build/main.css”中的样式,因为其 MIME 类型(“text/html”)不受支持

    My Ionic https en wikipedia org wiki Ionic mobile app framework 构建一直运行得很好 直到我想在我的 iPhone 上进行测试 所以我停止了我的服务器 做了一个ionic ser
  • 无需源代码即可部署网站

    我用php开发了网站 我想在没有源代码的情况下部署它 用php可以吗 我可以将网站代码转换为某种中间形式然后进行部署吗 您可以使用 Zend Guard 来编码您的代码 这样它就无法被逆向工程 http www zend com en pr
  • 我可以检测焦点来源吗? (Javascript、jQuery)

    快速提问 是否可以检测焦点是来自鼠标单击还是来自焦点事件的选项卡 我想如果没有 我将不得不在同一元素上使用单击句柄来确定源 但我更喜欢通过焦点事件的方式 Thanks Gausie 可能无法 100 工作 但如果没有直接的方法 那么你不能直
  • Gecko/Firefox 对 HTML5 通知的支持

    我想知道是否有任何内置支持HTML5 通知到目前为止 Gecko 浏览器有哪些功能 也许有一些隐藏的开发人员 我知道 WebKitwindow webkitNotifications效果很好 那么 有 Firefox 实现吗 Update
  • 如何判断CKEditor是否已加载?

    如何确定 CKEditor 是否已加载 我查看了API文档 但只能找到loaded事件 我想检查 CKEditor 是否已加载 因为如果我第二次加载它 我的文本区域就会消失 The loaded活动对我不起作用 instanceReady
  • 如何在没有模块的情况下在 vue 中使用 TypeScript

    In package json I have devDependencies vue 2 5 16 这给了我index d ts vue d ts and so on https github com vuejs vue tree v2 5
  • Javascript onclick隐藏div

    我想使用 javascript 隐藏这个警告 div 我的 javascript 正确吗 我想在单击关闭图标时隐藏 关闭 div images close icon gif div strong Warning strong These a
  • 在 Angular2 (TS) 中导入模块的选项

    我知道有一些进展或至少有计划 5093 https github com Microsoft TypeScript issues 5039 5728 https github com Microsoft TypeScript pull 57
  • JavaScript TypedArray 混合类型

    我正在尝试使用 WebGL 并希望将一些不同类型混合到一个字节缓冲区中 我知道 TypedArrays 可以达到这个目的 但不清楚我是否可以与它们混合类型 OpenGL 顶点数据通常是与无符号字节或整数混合的浮点数 在我的测试中 我想将 2
  • 如何自动加载 Webpack 中给定目录中的所有 JSON 文件? [复制]

    这个问题在这里已经有答案了 编辑 有一个现有的问题 https stackoverflow com questions 29421409 how to load all files in a subdirectories using web
  • gulp-uglify 不会保留文件顺序

    当我使用吞咽丑化 https github com terinjokes gulp uglify为了缩小 Javascript 文件 顺序变得混乱 可以说我让这个任务按预期工作 var gulp require gulp var renam
  • Google Hangouts 扩展程序如何创建面板窗口?

    The Doc http code google com chrome extensions windows html说如果你想创建一个面板窗口 你应该使用 chrome windows create type panel function
  • 与桌面浏览器相比,移动浏览器有多强大? [关闭]

    就目前情况而言 这个问题不太适合我们的问答形式 我们希望答案得到事实 参考资料或专业知识的支持 但这个问题可能会引发辩论 争论 民意调查或扩展讨论 如果您觉得这个问题可以改进并可能重新开放 访问帮助中心 help reopen questi

随机推荐