为何TypeScript导入自定义模块时需添加.js扩展名?
问题原因与解决方案
这是Node.js ES模块(ESM)的强制规则和TypeScript编译逻辑的差异导致的,具体拆解如下:
1. Node.js ESM的硬性要求
Node.js处理ES模块时,必须指定完整的文件扩展名(如.js、.mjs),它不会像CommonJS那样自动补全扩展名或查找index文件。如果你的package.json中设置了"type": "module",Node会将所有.js文件当作ESM处理,此时导入语句不带扩展名就会触发ERR_MODULE_NOT_FOUND错误。
2. TypeScript的编译映射逻辑
- 当你在
.ts文件中写import { MyClass } from './mymodule'时,TypeScript默认编译生成的.js文件里会原样保留这个无扩展名的路径,但Node.js不认这种写法。 - 而当你在
.ts中写import { MyClass } from './mymodule.js'时,TypeScript会智能映射:它知道你实际要导入的是.ts源文件,编译后生成的.js文件会保留./mymodule.js的路径,完全符合Node.js ESM的要求,因此能正常运行。
3. 为什么修改配置没生效?可能是配置没踩中关键点
要让TypeScript自动适配Node.js ESM的扩展名规则,需要同时调整tsconfig.json和package.json的核心配置:
- tsconfig.json:必须将
"module"设为"NodeNext"或"Node16",同时"moduleResolution"也设为"NodeNext"或"Node16"。这组配置会让TypeScript严格按照Node.js ESM的规则处理导入路径,编译时自动给生成的.js文件补上正确的扩展名。 - package.json:如果使用ESM,需添加
"type": "module";如果用CommonJS,则移除该字段,同时tsconfig.json的"module"要设为"CommonJS"。
示例配置
// tsconfig.json { "compilerOptions": { "module": "NodeNext", "moduleResolution": "NodeNext", "target": "ES2020", "outDir": "./dist" } }
// package.json { "type": "module", "scripts": { "build": "tsc", "start": "node dist/hello.js" } }
配置好后,你在.ts中写import { MyClass } from './mymodule',TypeScript会自动编译成带.js扩展名的导入路径,无需手动添加。
内容的提问来源于stack exchange,提问作者user2556468
相关产品推荐
相关产品推荐

