TypeScript项目启用原生ESM需严格遵循规范:导入路径须含扩展名或为有效包名,tsconfig.json中module设为"ESNext"、target≥"ES2020"、moduleResolution为"node16"/"nodenext"、allowImportingTsExtensions为false,并在package.json声明"type": "module";路径别名需构建工具或插件支持,运行时导入必须指向编译后的.js文件。

在 TypeScript 项目中启用原生 ES 模块(ESM)后,模块路径解析必须严格遵循 ESM 规范:导入路径需为完整、明确的文件路径(含扩展名)或有效包名,不再支持 CommonJS 风格的隐式扩展名补全(如自动尝试 .ts、.js、.d.ts)。配置错误会导致 Cannot find module 或 allowImportingTsExtensions is required 等典型报错。
确保 tsconfig.json 的核心模块选项匹配 ESM 要求
这是路径解析正确的前提。必须显式对齐编译目标与运行时环境:
-
module: "ESNext" —— 输出标准 ES 模块语法(
import/export),不转译为 CommonJS -
target: "ES2020" 或更高(如
ES2022)—— 保证语言特性兼容现代 ESM 运行时 -
moduleResolution: "node16" 或
"nodenext"—— 启用 Node.js v16+ 的 ESM 解析逻辑,支持exports字段、条件导出等 -
allowImportingTsExtensions: false —— 显式禁用该危险选项,避免编译输出中残留
.ts扩展名
package.json 必须声明 type: "module"
Node.js 仅凭此字段识别整个项目为 ESM 环境。缺失时,即使 TypeScript 编译出 import 语句,Node.js 仍以 CommonJS 方式加载,直接报错 Cannot use import statement outside a module:
{
"type": "module",
"main": "dist/index.js",
"types": "dist/index.d.ts"
}
注意:main 和 types 应指向 tsc 编译后的 .js 和 .d.ts 文件,而非源码 .ts 路径。
立即学习“Java免费学习笔记(深入)”;
在 Java 中初始化和管理阿里云 SDK客户端。包括单例模式、线程安全、endpoint 与 region 配置、VPC 终端节点、同步与异步等。
路径别名(baseUrl/paths)需由构建工具或运行时插件支持
TypeScript 的 baseUrl 和 paths 是编译期功能,原生 ESM 加载器完全忽略它们。若你在 tsconfig.json 中写了:
"compilerOptions": {
"baseUrl": "./src",
"paths": {
"@utils/*": ["utils/*"]
}
}
那么 import { helper } from "@utils/math"; 在开发时会通过 IDE 或 tsc 类型检查,但运行时 Node.js 无法解析 @utils —— 它不是合法包名,也不含扩展名。
解决方案是引入外部支持:
-
Vite / Webpack / Rollup:配置别名重写(如 Vite 的
resolve.alias),将@utils编译时转为相对路径 -
开发运行时:使用
ts-node+tsconfig-paths插件,让 Node.js 在 require 时动态解析别名 -
生产环境:确保构建产物中所有导入路径均为真实存在的
.js文件路径(含扩展名)
导入语句必须指向编译产物,而非源码
ESM 规范要求运行时加载的是实际文件。因此,所有 import 语句中的路径,应与 tsc --outDir 输出结构一致,并显式带 .js 扩展名:
- ✅ 正确(指向输出):
import { Button } from "./components/Button.js"; - ❌ 错误(指向源码):
import { Button } from "./src/components/Button.ts";(触发allowImportingTsExtensions报错) - ❌ 错误(无扩展名):
import { Button } from "./components/Button";(Node.js 不知道加载哪个文件)
这意味着你应在代码中习惯性写 .js,而不是依赖编辑器或旧习惯补全 .ts。构建工具(如 Vite)通常能自动处理开发时的路径映射,但最终产出必须符合 ESM 规则。

















