Skip to content

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 配置(推荐用于简单项目)

如果你想避免复杂的配置,最简单的解决方案是:

  1. package.json 中移除 "type": "module"
  2. tsconfig.json 中设置 CommonJS 模块系统

package.json:

json
{
  // 移除 "type": "module"
  "scripts": {
    "start": "ts-node src/App.ts"
  }
}

tsconfig.json:

json
{
  "compilerOptions": {
    "module": "CommonJS",
    "moduleResolution": "node"
    // 其他配置...
  }
}

TIP

这个方案适合大多数传统 Node.js 项目,避免了 ESM 的复杂性。

方案二:配置 ts-node 支持 ESM

如果你需要使用 ES 模块,需要正确配置 ts-node

package.json:

json
{
  "type": "module",
  "scripts": {
    "start": "ts-node --esm src/App.ts"
  }
}

tsconfig.json:

json
{
  "compilerOptions": {
    "module": "ESNext",
    "moduleResolution": "node"
    // 其他配置...
  },
  "ts-node": {
    "esm": true
  }
}

方案三:使用专门的 ESM 命令

ts-node 提供了一个专门的 ESM 版本:

bash
ts-node-esm src/App.ts

或者使用 Node.js 的加载器标志:

bash
node --loader ts-node/esm src/App.ts

方案四:使用替代工具

如果 ts-node 给你带来太多麻烦,可以考虑使用替代工具:

  1. tsx - 现代 TypeScript 运行时

    bash
    npm install -D tsx
    npx tsx src/App.ts
  2. vite-node - 基于 Vite 的 TypeScript 运行器

    bash
    npm install -D vite-node
    npx vite-node --watch src/App.ts
  3. Bun - 现代化的 JavaScript 运行时(如果不需要 Node.js)

    bash
    bun src/App.ts

完整配置示例

json
{
  "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"
  }
}
json
{
  "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"]
}
json
{
  "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'" 错误通常是由于模块系统配置不当导致的。根据你的项目需求:

  1. 对于简单项目,移除 "type": "module" 并使用 CommonJS
  2. 对于需要 ESM 的项目,正确配置 ts-nodeesm 选项
  3. 考虑使用现代替代工具如 tsxvite-node 以获得更好的开发体验

选择最适合你项目需求的解决方案,确保 TypeScript 配置与 Node.js 模块系统保持一致。