TypeScript 4.x编译使用逗号运算符导致this为undefined如何禁用
问题原因说明
TypeScript 4.0及以上版本针对CommonJS模块的导入编译逻辑做了合规性调整,为了严格对齐ECMAScript模块规范中「导入的方法作为普通函数调用时this不绑定到模块导出对象」的要求,会默认生成(0, 模块对象.方法)()的逗号运算符语法,这是有意设计的合规行为,没有直接的编译配置可以单独禁用该语法生成。
你遇到的getInfo执行时this为undefined的问题,本质是getInfo是Helper类的原型方法,强依赖调用时的this指向Helper实例,TypeScript 3.6版本的编译结果实际不符合ES规范,只是碰巧让this指向了模块导出对象,刚好适配了你的代码逻辑。
可行解决方案
方案1:调整导入方式(最便捷,无需修改依赖包)
不要使用解构语法导入getInfo,改为导入完整模块对象后直接调用对象上的方法,即可避免生成逗号运算符,运行效果和TS3.6完全一致:
// 原解构导入改为全量导入 import * as Helper from "helper" ... const CONFIG: Config[] = [ {name: "foo", info: [Helper.getInfo("foo")]}, {name: "bar", info: [Helper.getInfo("bar")]}, ]
方案2:修改Helper包导出逻辑(最彻底,无后续兼容问题)
如果有权限修改Helper包的代码,推荐在导出时提前把方法绑定到实例,或者改造为不依赖this的纯函数:
// Helper包内部代码示例 const helperInstance = new Helper(); // 导出前绑定this到实例,调用方怎么导入都不会丢失this export const getInfo = helperInstance.getInfo.bind(helperInstance);
方案3:调整编译配置(不推荐,可能影响其他依赖导入)
如果不想修改业务代码和依赖包,可以通过修改tsconfig.json的编译规则降级模块导入逻辑,恢复到3.6版本的编译效果:
{ "compilerOptions": { // 关闭ES模块兼容转换,恢复旧版CommonJS导入逻辑 "esModuleInterop": false, "allowSyntheticDefaultImports": false } }
该方案可能导致其他遵循ES模块规范的第三方包导入出错,除非临时过渡否则不建议使用。
内容的提问来源于stack exchange,提问作者0.618
相关产品推荐
相关产品推荐

