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

在TypeScript的CJS项目中动态加载ESM模块的问题

在TypeScript CommonJS项目中加载ESM模块的解决方案

我在TypeScript的CommonJS项目中尝试加载单个ESM模块,但找到的示例都是JavaScript版本。我的代码如下:

// example.ts
export const example = async () => {
  const module = await import("esm-module");
  return module.func
}

问题在于TS编译器会把import()操作符转译为require,转译后的代码完全无法正常加载ESM模块:

"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.example = void 0;
const example = async () => {
    const module = await Promise.resolve().then(() => require("esm-module")); // 非预期结果
    return module.func;
};
exports.example = example

解决方法

1. 调整TypeScript编译配置(推荐方案)

修改tsconfig.json,让TSC保留动态import()语法,不将其转译为require:

{
  "compilerOptions": {
    "module": "CommonJS",
    "target": "ES2020", // 动态import是ES2020特性,需指定至少该版本
    "moduleResolution": "NodeNext",
    "esModuleInterop": true,
    "skipLibCheck": true,
    "forceConsistentCasingInFileNames": true
  }
}
  • target: "ES2020":告诉TSC目标环境支持动态import(),因此不会转译该语法。
  • moduleResolution: "NodeNext":让TS遵循Node.js的模块解析逻辑,正确区分CJS和ESM模块。

编译后代码会保留原生的import(),这样Node.js就能正确加载ESM模块:

"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.example = void 0;
const example = async () => {
    const module = await import("esm-module");
    return module.func;
};
exports.example = example;

2. 手动使用createRequire(备选)

如果无法提升编译目标版本,可借助Node.js的createRequire工具,但这种方式仅适用于部分兼容CJS的ESM模块,纯ESM模块可能报错:

// example.ts
import { createRequire } from 'module';
const require = createRequire(import.meta.url);

export const example = async () => {
  const module = require("esm-module");
  return module.func;
};

3. 补充模块类型定义

若加载的ESM模块没有提供类型定义,需手动添加:

// types.d.ts
declare module 'esm-module' {
  export function func(): void;
  // 根据模块实际导出补充类型
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.24 13:33:26