Jest用TS作自定义testEnvironment时报ERR_UNKNOWN_FILE_EXTENSION错误
Jest 加载testEnvironment、setupFilesAfterEnv这类配置项指定的框架级入口文件时,不会走你在transform字段配置的测试文件转译流程,而是直接调用Node.js原生的require逻辑加载文件。
这套配置之前能正常运行,是因为原单仓库用npm/yarn安装依赖时,会自动做扁平化提升,其他依赖附带的TS运行时转译器(比如ts-node、各类swc注册包)会被隐式放到根目录node_modules下,Node启动Jest时会自动加载这些转译注册逻辑,可以直接识别.ts后缀。
迁移到pnpm monorepo后,pnpm默认采用严格的依赖隔离策略,不会做无限制的依赖扁平化提升,子包启动Jest时找不到之前隐式存在的TS转译注册器,Node原生无法识别.ts文件后缀,就会抛出ERR_UNKNOWN_FILE_EXTENSION错误。
清理缓存、重装依赖、切换@swc/jest/ts-jest都无法解决问题,是因为这些操作都没有触达「Jest启动阶段加载testEnvironment时TS转译逻辑未注册」的核心问题,和package.json里的"type": "module"配置也没有关联。
二选一即可,优先推荐方案1,改动量最小。
方案1:显式注册SWC运行时转译
你本身已经在用@swc/jest做测试文件转译,直接配套加运行时注册即可,不需要修改现有TS编写的testEnvironment代码:
- 在monorepo根目录或对应子包目录安装依赖(和你执行测试命令的目录保持一致即可):
pnpm add -D @swc-node/register
- 修改测试启动脚本,让Node启动时先加载SWC的TS转译注册逻辑,再启动Jest。把package.json里原本的测试命令(比如
"test": "jest")修改为:
"test": "node --require @swc-node/register ./node_modules/jest/bin/jest.js"
修改完成后,所有Jest启动阶段加载的.ts文件(包括自定义testEnvironment、setup文件)都会被SWC实时转译,不会再报文件后缀错误。
方案2:预编译testEnvironment为JS文件
如果不想引入运行时转译依赖,可以单独把自定义testEnvironment文件提前编译为JS:
- 配置SWC或tsc,把
source/testtools下的测试环境相关TS文件编译输出到独立目录(比如dist/testtools) - 修改jest.config.js里的
testEnvironment字段,指向编译后的JS文件路径,示例:<rootDir>/dist/testtools/jsdom-environment-global.js
这个方案测试启动速度更快,但需要额外维护测试环境文件的编译流程。
你当前的jest.config.js里有两处笔误,会导致对应路径的忽略规则失效,建议一并修复:testPathIgnorePatterns数组中的两个<rooDir>拼写错误,缺少字母t,需要改为<rootDir>。
内容的提问来源于stack exchange,提问作者Gernot Raudner

