如何在Mocha测试中从require切换为TypeScript的import语法?
我的package.json配置如下:
"scripts": { "test": "mocha -r ts-node/register security.test.ts" }, "type": "module", // ... 其他省略配置 "devDependencies": { "@types/mocha": "^10.0.1", "esm": "^3.2.25", "mocha": "^10.2.0", "ts-mocha": "^10.0.0", "ts-node": "^10.9.1", "typescript": "^5.1.3" }
tsconfig.json配置:
{ "compilerOptions": { "esModuleInterop": true, "module": "ESNext", "target": "ESNext", "resolveJsonModule": true, "moduleResolution": "Node" }, "ts-node": { "esm": true, "experimentalSpecifierResolution": "node" }, "include": [ "*.ts", "**/*.ts", "**/*.test.ts" ] }
security.test.ts内容:
import { describe, it, before, after } from "mocha"; describe("Testing for project", async () => { before(async () => { console.log("before"); }); after(async () => { console.log("ran after"); }); });
执行测试命令mocha -r ts-node/register security.test.ts时,总是遇到如下错误,只有改用require语句才能正常运行:
TypeError [ERR_UNKNOWN_FILE_EXTENSION]: Unknown file extension ".ts" for /myfilepath.ts at new NodeError (node:internal/errors:399:5) at Object.getFileProtocolModuleFormat [as file:] (node:internal/modules/esm/get_format:79:11) at defaultGetFormat (node:internal/modules/esm/get_format:121:38) at defaultLoad (node:internal/modules/esm/load:81:20) at nextLoad (node:internal/modules/esm/loader:163:28) at ESMLoader.load (node:internal/modules/esm/loader:605:26) at ESMLoader.moduleProvider (node:internal/modules/esm/loader:457:22) at new ModuleJob (node:internal/modules/esm/module_job:64:26) at ESMLoader.#createModuleJob (node:internal/modules/esm/loader:480:17) at ESMLoader.getModuleJob (node:internal/modules/esm/loader:434:34)
请问我遗漏了什么配置?切换到ES模块语法真的这么麻烦吗?
问题核心是你用了适配CommonJS的ts-node/register,但项目声明了"type": "module",Node会强制启用ES模块加载逻辑,两者不匹配导致扩展名解析失败。按以下步骤调整即可:
修改package.json的test脚本
直接用ts-mocha(已经在依赖里)简化命令:"test": "ts-mocha security.test.ts"或者保留mocha命令,改用ts-node的ES模块专用加载器:
"test": "mocha --loader ts-node/esm security.test.ts"ts-node/esm是专门为ES模块场景设计的加载器,比旧的register更适配你的配置。调整tsconfig.json的模块解析规则
把"moduleResolution": "Node"改成"moduleResolution": "NodeNext",和你设置的"module": "ESNext"对应,让TypeScript的模块解析逻辑和Node的ES模块规则完全对齐。移除冗余依赖
你已经配置了ts-node的ESM支持,esm包是旧的ES模块兼容方案,现在可以删掉:npm uninstall esm补全测试文件代码
你的security.test.ts里的describe块未闭合,加上});结尾,避免语法错误干扰执行。
调整完成后,重新运行测试命令就能正常使用import语法了。其实ES模块和TypeScript的配合只要对齐加载器和配置规则,并没有那么麻烦,核心是让ts-node、mocha、Node三者的模块逻辑保持一致。
内容的提问来源于stack exchange,提问作者Yan Digilov

