TypeScript 文件扩展名 ".ts" 未知错误解决方案
问题描述
当在 Heroku 或其他环境中尝试运行 TypeScript 应用程序时,可能会遇到以下错误:
TypeError [ERR_UNKNOWN_FILE_EXTENSION]: Unknown file extension ".ts" for /app/src/App.ts
这个错误通常发生在使用 ts-node
运行时,特别是在 package.json
中设置了 "type": "module"
的情况下。错误信息表明 Node.js 无法识别 .ts
文件扩展名,这通常是由于模块系统配置问题导致的。
根本原因
这个问题的主要原因是 TypeScript 配置与 Node.js 的 ESM(ECMAScript 模块)系统之间的不兼容。当使用 "type": "module"
时,Node.js 期望所有文件都是 ES 模块,但 ts-node
需要正确的配置才能处理 TypeScript 文件的转译。
解决方案
方案一:移除 ESM 配置(推荐用于简单项目)
如果你想避免复杂的配置,最简单的解决方案是:
- 从
package.json
中移除"type": "module"
- 在
tsconfig.json
中设置 CommonJS 模块系统
package.json:
{
// 移除 "type": "module"
"scripts": {
"start": "ts-node src/App.ts"
}
}
tsconfig.json:
{
"compilerOptions": {
"module": "CommonJS",
"moduleResolution": "node"
// 其他配置...
}
}
TIP
这个方案适合大多数传统 Node.js 项目,避免了 ESM 的复杂性。
方案二:配置 ts-node 支持 ESM
如果你需要使用 ES 模块,需要正确配置 ts-node
:
package.json:
{
"type": "module",
"scripts": {
"start": "ts-node --esm src/App.ts"
}
}
tsconfig.json:
{
"compilerOptions": {
"module": "ESNext",
"moduleResolution": "node"
// 其他配置...
},
"ts-node": {
"esm": true
}
}
方案三:使用专门的 ESM 命令
ts-node
提供了一个专门的 ESM 版本:
ts-node-esm src/App.ts
或者使用 Node.js 的加载器标志:
node --loader ts-node/esm src/App.ts
方案四:使用替代工具
如果 ts-node
给你带来太多麻烦,可以考虑使用替代工具:
tsx - 现代 TypeScript 运行时
bashnpm install -D tsx npx tsx src/App.ts
vite-node - 基于 Vite 的 TypeScript 运行器
bashnpm install -D vite-node npx vite-node --watch src/App.ts
Bun - 现代化的 JavaScript 运行时(如果不需要 Node.js)
bashbun src/App.ts
完整配置示例
{
"name": "your-project",
"version": "1.0.0",
"main": "dist/app.js",
"type": "module",
"scripts": {
"dev": "nodemon",
"start": "ts-node --esm src/App.ts"
},
"dependencies": {
// 你的依赖
},
"devDependencies": {
"@types/node": "^20.0.0",
"typescript": "^5.0.0",
"ts-node": "^10.9.0",
"nodemon": "^3.0.0"
}
}
{
"compilerOptions": {
"target": "ES2022",
"module": "ESNext",
"moduleResolution": "node",
"esModuleInterop": true,
"outDir": "dist",
"strict": true,
"skipLibCheck": true,
"forceConsistentCasingInFileNames": true
},
"ts-node": {
"esm": true,
"experimentalSpecifierResolution": "node"
},
"include": ["src/**/*.ts"],
"exclude": ["node_modules"]
}
{
"watch": ["src"],
"ext": "ts",
"exec": "ts-node --esm src/App.ts"
}
版本兼容性说明
WARNING
某些 Node.js 版本(特别是 v18)与 ts-node
的 ESM 支持存在兼容性问题。如果你遇到问题,可以尝试:
- 降级到 Node.js v16
- 升级到 Node.js v20+
- 使用替代工具如
tsx
总结
"Unknown file extension '.ts'" 错误通常是由于模块系统配置不当导致的。根据你的项目需求:
- 对于简单项目,移除
"type": "module"
并使用 CommonJS - 对于需要 ESM 的项目,正确配置
ts-node
的esm
选项 - 考虑使用现代替代工具如
tsx
或vite-node
以获得更好的开发体验
选择最适合你项目需求的解决方案,确保 TypeScript 配置与 Node.js 模块系统保持一致。