在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
相关产品推荐
相关产品推荐

