typescript 中规范使用 es modules 导入需严格遵循路径带 .js 扩展名、区分命名/默认导入、类型导入加 type 前缀、配置 "module": "esnext" 与 "verbatimmodulesyntax": true 等规则。

在 TypeScript 中规范使用 ES Modules 导入,核心是兼顾类型安全、编译正确性与运行时兼容性。关键不在“能不能写”,而在“怎么写才不踩坑”——尤其当项目启用原生 ESM("type": "module")时,路径、扩展名、导出形式都必须严格符合规范。
导入路径必须带明确扩展名(.js 或 .mjs)
ESM 规范要求导入语句中的路径必须是完整、可解析的文件路径。TypeScript 源码(.ts)不能直接在运行时被 Node.js 加载,因此所有 import 路径都不能写 .ts 扩展名。
- ✅ 正确(开发时写 .js,构建后由工具保证存在):
import { User } from "./user.js"; - ❌ 错误(.ts 不是合法运行时模块路径):
import { User } from "./user.ts";→ 运行时报Cannot find module - ⚠️ 不推荐(启用
allowImportingTsExtensions会破坏构建一致性,且仅适用于 Deno 等非标准环境)
区分命名导入与默认导入,避免混用
一个模块可有多个命名导出(export const x = ...),但最多一个默认导出(export default ...)。导入时语法必须匹配导出方式:
- 命名导出 → 命名导入:
export const apiHost = "https://api.example.com";
→import { apiHost } from "./config.js"; - 默认导出 → 默认导入:
export default class Logger { ... }
→import Logger from "./logger.js"; - 混合导入(同时需要默认 + 命名):
import Logger, { LEVEL_DEBUG } from "./logger.js";
类型导入需显式加 type 前缀(TS 4.5+)
当只导入类型(如 interface、type alias),且该导入在编译后应被完全擦除(不生成 JS 代码),必须用 type 明确标注,否则可能触发运行时错误或打包异常:
- ✅ 类型专用导入:
import type { ApiResponse } from "./api.js"; - ✅ 同时导入值和类型(推荐分离):
import { fetchData } from "./api.js";<br>import type { ApiResponse } from "./api.js"; - ❌ 避免无前缀导入类型(尤其在
verbatimModuleSyntax: true下会报错):import { ApiResponse } from "./api.js";
构建与配置要协同一致
规范导入不是单靠写法,还需配套配置:
- tsconfig.json 中设置:
"module": "esnext"(对应 ESM 输出)"moduleResolution": "bundler"(推荐,适配现代打包器行为)"verbatimModuleSyntax": true(强制区分值/类型导入,提升安全性) - 确保构建工具(Vite、esbuild、SWC)输出的
.js文件与源码.ts结构一一对应,并保留正确的.js扩展名路径 - 不依赖
"allowSyntheticDefaultImports"或"esModuleInterop"来“修复”错误写法——它们只是补丁,掩盖了路径或导出不规范的本质
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











