ts-jest --watch模式无法检测导入类属性变更问题
问题说明
- 执行
jest --watch或jest --watchAll进入监听模式后,删除Card类的value属性、构造函数对应v参数的相关代码并保存,测试用例仍会通过,预期的参数数量不匹配错误不会触发 - 终止Jest进程重新全量执行测试、或者单独保存测试文件
card_types.test.ts时,才能正确抛出类型错误 - 启动命令添加
--no-cache参数无法解决该问题
问题复现步骤
- 执行命令
jest --watchAll --no-cache(--no-cache参数实测无效果) - 删除
card_types.ts中所有标注了value的相关代码行后保存 - 观察到测试用例依然通过
- 终止Jest进程重新执行测试,测试会因参数数量不匹配正确失败
相关项目文件
card_types.ts
export class Card { // can add things like image and such here. readonly category: string; readonly value: number; //<----- Remove me constructor(c: string, v: number) { //<----- Remove ", v: number" this.category = c; this.value = v; //<----- Remove me } }
card_types.test.ts
import { Card } from './card_types'; describe('Card Class', () => { it('should create an instance of Card with category = Action', () => { const my_card = new Card('Action'); console.log(my_card); expect(my_card.category).toBe('Action'); }); });
tsconfig.json
{ "compilerOptions": { "target": "es2016", "module": "commonjs", "esModuleInterop": true, "forceConsistentCasingInFileNames": true, "strict": true, "skipLibCheck": true } }
jest.config.js
/** @type {import('ts-jest/dist/types').InitialOptionsTsJest} */ module.exports = { globals: { 'ts-jest': { tsconfig: 'tsconfig.json', }, }, preset: 'ts-jest', testEnvironment: 'node', testMatch: ['**/*.test.(ts|js)'], };
问题根因
这个问题是ts-jest监听模式下的增量编译机制导致的:
- 默认配置下
ts-jest为了提升watch模式的运行速度,会开启增量编译缓存,仅对发生变更的单个文件做类型校验,不会重新校验依赖该文件的关联文件 - 修改
card_types.ts(非测试文件)时,ts-jest只转译了这个文件本身,没有重新检查引用它的card_types.test.ts的类型,测试文件里旧的类型缓存没有更新,所以不会抛出参数不匹配错误 - 保存测试文件时,测试文件本身被标记为变更,会触发关联依赖的类型重新扫描;重启Jest时会清空内存中的编译缓存做全量检查,所以这两种场景能正常报错
--no-cache参数只会清除Jest本身的转译产物缓存,不会清除ts-jest内部TypeScript编译服务的内存缓存,所以加了也没用
解决方案
直接修改jest.config.js中的ts-jest配置,关闭增量编译和单文件隔离转译,强制跨文件类型检查即可:
/** @type {import('ts-jest/dist/types').InitialOptionsTsJest} */ module.exports = { globals: { 'ts-jest': { tsconfig: 'tsconfig.json', isolatedModules: false, // 关闭单文件隔离编译,启用跨文件类型校验 incremental: false, // 关闭ts-jest增量编译缓存 }, }, preset: 'ts-jest', testEnvironment: 'node', testMatch: ['**/*.test.(ts|js)'], };
如果觉得关闭增量编译后watch模式速度太慢,可以升级到v29及以上版本的ts-jest,新版本已经修复了大部分watch模式下跨文件类型检查的缓存失效问题。
临时规避方案:修改源文件后,给对应测试文件加个空行再保存,就能触发关联类型重检。
注:提供的初始代码本身就存在类型问题:
Card构造函数定义需要2个参数,但测试中仅传入1个,首次全量运行测试就会抛出参数不匹配错误,验证修复效果前需要先把测试代码调整为符合当前类定义的写法。
内容的提问来源于stack exchange,提问作者Matthew
相关产品推荐
相关产品推荐

