You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Node.js+TypeScript+ts-node搭建ESM项目遇.ts扩展名错误

问题描述

我要搭建一个基于Node.js、TypeScript、ts-node的ESM模块项目,因为部分NPM库最新版本要求ESM,所以需要把TypeScript代码编译成ESM而非CommonJS。但运行index.js时一直报错:TypeError [ERR_UNKNOWN_FILE_EXTENSION]: Unknown file extension ".ts" for SomeClass.ts。

相关代码如下:

index.js

import TsNode           from "ts-node";

const tsNodeService = TsNode.register({
    transpileOnly: false
});

TsNode.createEsmHooks(tsNodeService); //试过添加和移除该行

(async () => {    
    const SomeClass = await import("./SomeClass.ts");

    console.log(new SomeClass().method("abc", 123));
})();

// 也尝试过以下写法:
/*
import SomeClass from "./SomeClass.ts";

console.log(new SomeClass().method("abc", 123));
*/

SomeClass.ts

export default class SomeClass {
    method(a: string, b: number) {
        return `${a} and ${b}`;
    }
}

tsconfig.json

{
    "$schema": "https://json.schemastore.org/tsconfig",

    "compilerOptions": {
        "baseUrl":  "./",
        "outDir":   "./output/",

        "module":   "Node16",
        "target":   "ES2022",

        "strict":                       true,
        "strictPropertyInitialization": false,
        "esModuleInterop":              true,
        "noImplicitAny":                true,
        "removeComments":               true,
        "preserveConstEnums":           true,
        "sourceMap":                    true,
        "pretty":                       true,
        "experimentalDecorators":       true,
        "allowJs":                      true,
        "resolveJsonModule":            true
    },

    "exclude": [
        "node_modules/**/*"
    ]
}

package.json

{
  "name": "testesmts",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "author": "",
  "type": "module",
  "license": "ISC",
  "dependencies": {
    "ts-node": "^10.9.1",
    "typescript": "^4.9.3"
  }
}
解决方案

以下是解决该问题的关键步骤:

  • 调整package.json配置,添加启动脚本
    保留type: "module",新增ts-node的ESM启动脚本,无需手动注册ts-node:

    {
      "name": "testesmts",
      "version": "1.0.0",
      "type": "module",
      "scripts": {
        "start": "ts-node --esm ./index.ts"
      },
      "dependencies": {
        "ts-node": "^10.9.1",
        "typescript": "^4.9.3"
      }
    }
    
  • 完善tsconfig.json的ESM解析配置
    确保moduleResolution与module一致,启用Node16的ESM解析规则:

    {
      "$schema": "https://json.schemastore.org/tsconfig",
      "compilerOptions": {
        "baseUrl": "./",
        "outDir": "./output/",
        "module": "Node16",
        "target": "ES2022",
        "moduleResolution": "Node16", // 必须配置此项,匹配Node16的模块解析逻辑
        "strict": true,
        "strictPropertyInitialization": false,
        "esModuleInterop": true,
        "noImplicitAny": true,
        "removeComments": true,
        "preserveConstEnums": true,
        "sourceMap": true,
        "experimentalDecorators": true,
        "allowJs": true,
        "resolveJsonModule": true,
        "skipLibCheck": true
      },
      "exclude": ["node_modules/**/*"]
    }
    
  • 将入口文件改为TS格式,简化代码
    删除原index.js,创建index.ts作为入口,避免手动注册ts-node的复杂操作:

    // 静态导入写法
    import SomeClass from "./SomeClass.ts";
    console.log(new SomeClass().method("abc", 123));
    
    // 或动态导入写法(需解构default导出)
    /*
    (async () => {    
      const { default: SomeClass } = await import("./SomeClass.ts");
      console.log(new SomeClass().method("abc", 123));
    })();
    */
    
  • 用正确命令启动项目
    执行npm start,或直接运行:

    ts-node --esm ./index.ts
    

    不要直接运行index.js,因为ESM模式下Node.js无法自动识别.ts文件扩展名,必须由ts-node处理。

  • 移除多余的手动注册代码
    原index.js中的TsNode.register和createEsmHooks代码完全不需要,ts-node --esm参数会自动处理ESM环境下的TS文件解析、转译逻辑。

内容的提问来源于stack exchange,提问作者Sonaht

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.11 03:55:30