TypeScript编译后JS运行报错:Cannot use import statement outside of a module
SyntaxError: Cannot use import statement outside a module的问题 我来帮你梳理下问题根源和解决办法,你遇到的矛盾其实是模块系统不匹配导致的,一步步来解决:
1. 先排查核心问题:为什么编译后的文件里还有import语句?
你的tsconfig设置了"module": "commonjs",正常情况下TypeScript会把所有ES模块的import转成CommonJS的require。如果编译后的User.model.js里还保留着import,大概率是下面两个原因:
原因1:该文件没被TypeScript编译
检查你的tsconfig.json的include配置,确保它包含了所有需要编译的TS文件,比如:
"include": ["src/**/*"]
同时确认User.model.ts在src目录下,且没有被exclude配置排除。运行npm run build后,去dist目录下找对应的User.model.js,打开看看里面是不是用了require而不是import。
原因2:代码里导入路径写了.ts后缀
如果你的TS代码里是这样导入的:
import { User } from './User.model.ts';
编译后生成的JS文件会保留这个后缀,变成:
const { User } = require('./User.model.ts');
Node运行时会尝试加载.ts文件,但它默认不识别TS语法,自然会报错import不能用。正确的写法是去掉.ts后缀:
import { User } from './User.model';
TypeScript会自动处理后缀,编译后会生成正确的require('./User.model.js')。
2. 为什么"type": "module"会引发新错误?
当你在package.json里加"type": "module",Node会把所有.js文件当作ES模块处理,但你的TS编译目标是CommonJS("module": "commonjs"),编译后的JS文件会包含exports、module.exports这类CommonJS语法,ES模块环境下不识别这些变量,所以会出现ReferenceError: exports is not defined。
这两种模块系统不能混用,所以你必须二选一:
- 要么用CommonJS(保持
"module": "commonjs",不要加"type": "module") - 要么用ES模块(把
"module": "ESNext"或"ES6",同时加"type": "module",并且所有导入路径要加.js后缀——这就是你说的“要求所有导入都添加.js后缀”的原因,因为ES模块在Node里必须写完整后缀)
显然你不想用ES模块的后缀要求,那我们就回到CommonJS的方案。
3. 最终解决方案步骤
- 恢复
package.json:移除"type": "module"配置,保持原来的脚本。 - 修正
tsconfig.json:确保include包含所有TS文件,比如:{ "compilerOptions": { "target": "ES6", "module": "commonjs", "outDir": "./dist", "rootDir": "./src" }, "include": ["src/**/*"], "exclude": ["node_modules"] } - 检查所有导入路径:确保TS代码里的导入都不包含
.ts后缀。 - 重新编译运行:先执行
npm run build(或npm run watch),确认dist目录下的所有JS文件都是CommonJS语法(用require而非import),再执行npm run start:dist。
如果还是有问题,可以检查你的最小复现仓库里的User.model.ts和导入它的文件,确认路径是否正确,以及该文件是否被正确编译到dist目录。
内容的提问来源于stack exchange,提问作者Loupi

