TypeScript错误TS2339:跨类方法绑定上下文引发类型校验问题
解决TypeScript中绑定this后类型校验错误的问题
这个问题我之前也碰到过——TypeScript的静态类型检查没法自动识别bind(this)带来的this指向变更,所以会误判keyPress方法里的this类型。下面给你几个靠谱的解决办法:
方法1:显式指定keyPress方法的this类型
TypeScript支持在函数的第一个参数位置声明this的类型,用来告诉编译器这个函数运行时的this指向。你可以修改DomService里的keyPress方法:
// 在DomService中修改keyPress方法 keyPress(this: ModalService, event: KeyboardEvent) { if (event.which === key.escape) { event.preventDefault(); this.hide(); // 现在TS知道this是ModalService,不会报错了 } }
这样做的好处是从根源上解决类型问题,让TS明确知道这个方法被调用时的this上下文。如果这个keyPress方法本来就是专门给ModalService使用的,这是最干净的方案。
方法2:在ModalService中包装一个中间函数
如果不想修改DomService的代码,可以在ModalService里写一个箭头函数作为中转,利用箭头函数自动绑定当前this的特性,再通过call把this传给keyPress:
// 在ModalService内部定义 private handleEscapeKey = (event: KeyboardEvent) => { // 用call指定this为ModalService实例 this.domService.keyPress.call(this, event); }; // 绑定事件时用这个中间函数 document.body.addEventListener('focus', this.handleEscapeKey, true);
这种方式不需要改动DomService,把上下文绑定的逻辑封装在ModalService内部,解耦性更好,而且TS能完美识别this的类型。
方法3:使用类型断言绕过检查(不推荐)
如果以上两种方法都不适用,你可以用类型断言强制告诉TS绑定后的函数类型:
document.body.addEventListener( 'focus', // 断言为(event: KeyboardEvent) => void,让TS忽略this类型检查 this.domService.keyPress.bind(this) as (event: KeyboardEvent) => void, true );
不过这种方法相当于关闭了TS对这段代码的类型校验,失去了TypeScript的类型安全优势,除非万不得已,尽量不要用。
内容的提问来源于stack exchange,提问作者Kolby




