You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

ESM项目导入CJS默认导出类实例化触发TypeError

ESM项目导入CJS默认导出类时报"TypeError: TestClass is not a constructor"的问题解析与解决

这是ESM与CJS模块互操作的已知兼容性问题,并非你的操作错误。

问题本质

当ESM(你的项目)导入CJS模块(依赖包)时,Node.js会将整个CJS模块封装为一个命名空间对象——即使CJS模块设置了__esModule: true,ESM默认导入的结果依然是这个模块对象,而非exports.default指向的类。此时你尝试new TestClass,本质是在实例化一个模块对象,自然会报"不是构造函数"的错误。

而当你移除项目的"type": "module"时,项目切换为CJS模式,Node.js的require会自动处理带有__esModule标记的模块,直接返回exports.default的内容,因此能正常运行;命名导出则不受互操作逻辑影响,所以也能正常工作。

解决方案

方案1:手动修正导入逻辑

直接在代码中显式获取CJS模块的default导出:

// 方式1:命名空间导入后取default
import * as TestModule from "testpackage";
const TestClass = TestModule.default;
new TestClass({ arg1: "Hello, World!" });

// 方式2:重命名导入
import { default as TestClass } from "testpackage";
new TestClass({ arg1: "Hello, World!" });

方案2:调整TypeScript配置,启用互支持

修改项目的tsconfig.json,启用合成默认导入与ES模块互操作选项,同时匹配ESM的模块解析规则:

{
    "include": ["src"],
    "compilerOptions": {
        "outDir": "dist",
        "lib": ["es2023"],
        "target": "es2022",
        "module": "ESNext", // 匹配ESM项目类型
        "moduleResolution": "nodenext",
        "allowSyntheticDefaultImports": true, // 允许对CJS模块使用默认导入语法
        "esModuleInterop": true // 启用ES与CJS互操作适配
    }
}

此配置会让TypeScript在编译时自动处理CJS模块的默认导出,既解决编译报错,也能保证运行时的正确性。

方案3:修改依赖包(若有权限)

如果可以修改依赖包的代码或配置,有两种优化方向:

  • 改用命名导出:将依赖包的默认导出改为命名导出,彻底规避互操作问题
    // 依赖包testFile.ts
    export class TestClass {
        constructor({ arg1 }: { arg1: string }) {
            console.log(arg1);
        }
    }
    
    项目中导入方式改为:
    import { TestClass } from "testpackage";
    
  • 双格式输出:让依赖包同时生成ESM和CJS版本,在package.json中配置exports字段做条件导出:
    // 依赖包package.json
    "exports": {
        ".": {
            "import": "./dist/esm/testFile.js",
            "require": "./dist/cjs/testFile.js"
        }
    }
    
    同时调整依赖包的tsconfig,通过多配置文件生成两种格式的输出。

内容的提问来源于stack exchange,提问作者DashwoodIce9

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.20 00:54:59