- 测试
- 开发工具
【免费下载链接】ts-jest
A Jest transformer with source map support that lets you use Jest to test projects written in TypeScript.
ts-jest是一个带 Source Map 支持的 Jest transformer)为核心骨架,结合仓库源码与配套文档,为你梳理 ts-jest 的能力边界、与 Babel 方案的取舍、快速上手步骤、核心配置以及底层处理流程,读完后你将能独立完成 TypeScript 项目的 Jest 测试环境搭建与调优。
ts-jest 是什么
根据项目官方定位(见 README.md 与 website/docs/introduction.md):
ts-jest 是一个带 Source Map 支持的 Jest transformer,它让你可以使用 Jest 测试用 TypeScript 编写的项目。
围绕这一定位,有三个关键能力值得展开:
- 它是一个 Jest transformer:在 Jest 的代码转换链路中,ts-jest 通过 Jest 的
transform配置被挂载到.ts/.tsx等文件的处理流程上,负责把这些文件编译成 Jest 可以执行的 JavaScript。 - 带 Source Map 支持:编译产物会携带 Source Map,因此当测试失败或抛出异常时,Jest 能够把堆栈信息映射回原始的
.ts源文件,错误定位准确、调试体验友好。 - 支持 TypeScript 的全部特性,包括类型检查:这是 ts-jest 区别于纯转译方案(如 Babel)的核心卖点——它不只是"去掉类型注解",而是真正以 TypeScript 编译器 API 驱动,在测试运行的同时进行类型检查(见 website/docs/babel7-or-ts.md)。
一个值得注意的细节是:ts-jest 项目自身也使用 ts-jest 来测试自己(README 的 "Built With" 一节明确写了ts-jest uses itself for its tests)。这意味着该项目每天都要在"自己编译自己、自己测试自己"的场景下运行,其 transformer 的正确性与健壮性由项目自身的测试套件背书。
入口与实现:一个 "createTransformer" 的包
从源码结构看,ts-jest 的对外入口非常简洁。在 src/index.ts 中,包默认导出了一个包含createTransformer(tsJestConfig?)方法的对象,该方法返回TsJestTransformer实例:
export default { createTransformer(tsJestConfig?: TsJestTransformerOptions) { return new TsJestTransformer(tsJestConfig) }, }TsJestTransformer的核心实现位于 src/legacy/ts-jest-transformer.ts,它实现了 Jest 的SyncTransformer接口,提供了process/processAsync/getCacheKey/getCacheKeyAsync等方法,并在构造时缓存ConfigSet、维护编译器实例与依赖图(depGraphs),从而保证同一测试进程中多次转换可以复用编译结果。
为什么需要 transformer:Jest 并不原生理解 TypeScript
Jest 本身只能直接执行 JavaScript。对于.ts/.tsx文件,Jest 需要借助 transformer 在require()之前将其转换为 JavaScript。ts-jest 正是承担这一职责的官方推荐的 TypeScript transformer。
安装并配置好 ts-jest 后,Jest 对每个文件的处理流程大致是:
- 判断该文件是否有对应的 transform 规则;
- 若 transformer 提供了
getCacheKey,则用它计算缓存键; - 若命中缓存则直接使用缓存内容,否则调用
transformer.process(...)编译文件并更新缓存; - 最终
require()编译后的产物。
这一流程的详细 PlantUML 描述见仓库内部文档 website/docs/processing.md。
ts-jest 与 Babel7 + @babel/preset-typescript 的对比
2018 年 9 月 Babel 7 发布,带来了@babel/preset-typescript,目标是让 Babel 用户无需迁移即可通过添加一个 preset 来尝试 TypeScript。那么既然 Babel 也能处理 TypeScript 语法,为什么还需要 ts-jest?
官方文档 website/docs/babel7-or-ts.md 系统性地列出了@babel/preset-typescript的局限——以下这些 TypeScript(与 ts-jest)能做到、而 Babel 做不到的事情,正是选择 ts-jest 的关键理由。
没有类型检查
这是使用 TypeScript(而非 Babel)的最大优势:开箱即用的类型检查。
在使用 ts-jest 时,文件在编译的同时会被类型检查,从而获得更流畅的 TDD(测试驱动开发)体验。下面这段代码,TypeScript 会直接报错,而 Babel 则不会:
const str: string = 42Babel 将文件当作相互孤立的模块逐一转译,不存在"项目"的概念;而 TypeScript 中文件属于一个项目(project),是在项目作用域内统一编译的。这意味着跨文件的类型关系、import类型推断等都能被正确校验。
不支持namespace
namespace app { export const VERSION = '1.0.0' export class App { /* ... */ } }Babel 的preset-typescript无法处理这种命名空间语法。
不支持const enum
const enum Directions { Up, Down, Left, Right, }const enum会被 TypeScript 编译器内联展开,Babel 按文件独立转译时无法完成这种跨文件的内联。
不支持声明合并
Babel 无法处理enum、namespace等类型的声明合并(declaration merging)特性。
不支持 legacyimport/export
import lib = require('lib') // ... export = myVar这类历史遗留的导入导出语法同样超出 Babel preset 的能力范围。
开启 JSX 时不支持尖括号类型断言
const val = <string>input当 TSX/JSX 开启时,尖括号会被解析为 JSX 语法,Babel 无法把它当作类型断言处理,而 ts-jest 基于 TypeScript 编译器则没有这个问题。
总结:如果你的项目用到了上述任一特性,或者希望在测试运行过程中同步获得类型检查保障,ts-jest 是比 Babel +preset-typescript更完整的选择。
快速开始:安装、配置与运行
以本仓库官方文档 website/docs/getting-started/installation.md 为准,最快三步即可跑通。
1. 安装依赖
将 jest、typescript、ts-jest 与 @types/jest 一次性安装为开发依赖:
npm install --save-dev jest typescript ts-jest @types/jest如果你的项目使用 TypeScript 7,不要直接安装typescript,而应遵循官方推荐的并排(side-by-side)编译器方案,详见 website/docs/guides/typescript-7.md。
2. 创建 Jest 配置
默认情况下 Jest 无需任何配置文件即可运行,但它不会编译.ts文件。要让 Jest 使用 ts-jest 转译 TypeScript,需要创建一份告知 Jest 使用 ts-jest preset 的配置文件。
ts-jest 可以自动生成配置文件:
npx ts-jest config:init使用 yarn 时对应:
yarn ts-jest config:init该命令会创建一份基础的 Jest 配置文件,告知 Jest 如何正确处理.ts文件。如果你在安装时遇到npx: command not found之类的报错,可以把npx XXX替换为node node_modules/.bin/XXX(在项目根目录下执行)。
此外,你也可以使用create-jest命令(同样以npx或yarn前缀)来获得更多 Jest 相关选项;但对其中的 TypeScript 询问要回答no,然后在生成的jest.config.js中手动加入一行:preset: "ts-jest"。
官方给出的全流程速查表如下:
| 步骤 | npm | yarn |
|---|---|---|
| 前置依赖(TypeScript 4.3–6) | npm i -D jest typescript | yarn add --dev jest typescript |
| 安装 | npm i -D ts-jest @types/jest | yarn add --dev ts-jest @types/jest |
| 创建配置 | npx ts-jest config:init | yarn ts-jest config:init |
| 运行测试 | npm test或npx jest | yarn test或yarn jest |
3. 运行测试
直接执行npm test或npx jest即可。此时.ts/.tsx文件会被 ts-jest 转译,且转换产物携带 Source Map,错误堆栈会指向原始 TypeScript 源码。
相关配置入口
如需进一步定制 Jest,请参考 Jest 官方配置指南;ts-jest 特有的配置项汇总在 website/docs/getting-started/options.md。若使用 ESM 项目,还需要阅读 website/docs/guides/esm-support.md。
核心配置选项一览
所有 ts-jest 专属选项都可以定义在 Jest 的transform配置对象中,既可以写在package.json里,也可以通过jest.config.js或jest.config.ts文件提供。
当使用 TypeScript 编写 Jest 配置文件时,Jest 会借助ts-node来编译该配置文件,ts-jest 不参与这一过程(见 website/docs/getting-started/options.md 的注意事项)。
官方列出的选项总表如下:
| 选项 | 说明 | 类型 | 默认值 |
|---|---|---|---|
compiler | 用作编译器的 TypeScript 模块 | string | "typescript" |
tsconfig | TypeScript 编译相关配置 | string|object|boolean | auto |
isolatedModules | 关闭类型检查(按隔离模块编译) | boolean | disabled |
astTransformers | 自定义 TypeScript AST 转换器 | object | auto |
diagnostics | 诊断信息相关配置 | boolean|object | enabled |
babelConfig | Babel(Jest) 相关配置 | boolean|string|object | disabled |
stringifyContentPathRegex | 匹配的文件将变成返回自身内容的模块 | string|RegExp | disabled |
useESM | 启用 ESM 支持 | boolean | auto |
注意:如果你使用自定义的
transform配置,请从 Jest 配置中移除preset,避免 Jest 不能正确转换文件(官方文档明确警告过这一点)。
tsconfig 选项的三种用法
tsconfig选项允许你指定要使用的tsconfigJSON 文件,也可以直接内联一份 compilerOptions 对象(详见 website/docs/getting-started/options/tsconfig.md)。
默认情况下,ts-jest 会在你的项目中查找tsconfig.json;若找不到,则使用 TypeScript 默认的 compilerOptions,唯一例外是target使用ES2015而不是默认的ES5。如果你希望即使项目里存在tsconfig.json也强制使用默认值,可以将该选项设为false。
指定配置文件路径(路径相对于启动 Jest 的目录,也支持<rootDir>前缀):
import type { Config } from 'jest' const jestConfig: JestConfigWithTsJest = { // [...] transform: { // '^.+\\.[tj]sx?$' 处理 ts,js,tsx,jsx // '^.+\\.m?[tj]sx?$' 处理 ts,js,tsx,jsx,mts,mjs,mtsx,mjsx '^.+\\.tsx?$': [ 'ts-jest', { tsconfig: 'tsconfig.test.json', }, ], }, } export default jestConfig内联 compilerOptions(等同于写在tsconfig.json的compilerOptions里的对象):
const jestConfig: Config = { // [...] transform: { '^.+\\.tsx?$': [ 'ts-jest', { tsconfig: { importHelpers: true, }, }, ], }, }禁用自动查找:
const jestConfig: Config = { // [...] transform: { '^.+\\.tsx?$': [ 'ts-jest', { tsconfig: false, }, ], }, }isolatedModules:以性能换取类型检查
默认情况下 ts-jest 在"项目"上下文中使用 TypeScript 编译器,具备完整的类型检查与全部特性。但它也可以把每个文件当作独立的"隔离模块"分别编译,这就是isolatedModules选项(默认false)的作用(详见 website/docs/getting-started/options/isolatedModules.md)。
开启后会失去类型检查能力,以及const enum等特性;但在配合jest --no-cache运行时,测试会明显更快:
const jestConfig: Config = { // [...] transform: { '^.+\\.tsx?$': [ 'ts-jest', { isolatedModules: true, }, ], }, }注意:该配置页已被标记为 DEPRECATED,官方建议改用
tsconfig.json中的isolatedModules选项,未来大版本中会移除 ts-jest 侧的isolatedModules配置。
性能提示与注意事项
使用isolatedModules: false(即开启类型检查)时性能相对更慢,可以通过收窄tsconfig.json中include的文件范围来提升性能——include提供的文件越少,测试运行能获得的性能提升越大:
{ // ...其他配置 "include": ["my-typings/*", "my-global-modules/*"] }但代价是 ts-jest 可能无法识别所有打算配合 Jest 使用的文件,自定义类型、全局模块等可能出问题。官方给出的建议是:让测试环境真正需要的文件被include的 glob 模式覆盖到,从而兼顾性能提升与不破坏现有行为。
预设(Presets)与编程式配置
Jest 中的 preset 是预定义的配置,用来标准化测试环境的搭建。ts-jest 提供了多组高度定制化的 preset,官方推荐的最佳实践是调用 preset 创建函数来生成(并可扩展)配置,而将旧的字符串形式 preset 视为 legacy 方案(详见 website/docs/getting-started/presets.md)。
以最常用的createDefaultPreset为例(其实现见 src/presets/create-jest-preset.ts):
import { createDefaultPreset, type JestConfigWithTsJest } from 'ts-jest' const presetConfig = createDefaultPreset({ //...options }) const jestConfig: JestConfigWithTsJest = { ...presetConfig, } export default jestConfigcreateDefaultPreset(options)返回一个包含transform属性的对象,将'^.+.tsx?$'映射到['ts-jest', TsJestTransformerOptions]。可选参数包括tsconfig、isolatedModules、compiler、astTransformers、diagnostics、stringifyContentPathRegex,每个参数都有独立的官方说明页(见 website/docs/getting-started/options 下的子页面)。
除默认 preset 外,ts-jest 还提供:
createDefaultLegacyPreset:legacy 版默认配置,transform 指向ts-jest/legacy;createDefaultEsmPreset:ESM 配置,处理.ts/.mts/.tsx/.mtsx,并额外设置extensionsToTreatAsEsm与useESM: true;createJsWithTsPreset:同时处理 JS 与 TS 文件(.js/.jsx/.ts/.tsx);createJsWithTsEsmPreset:ESM 版 JS+TS 配置;createJsWithBabelPreset及 ESM/legacy 变体:TS 文件交给 ts-jest,JS 文件交给babel-jest。
从源码可以看到这些函数的真实返回结构,例如createJsWithBabelPreset在 src/presets/create-jest-preset.ts 中同时设置了[JS_TRANSFORM_PATTERN]: 'babel-jest'与[TS_TRANSFORM_PATTERN]: ['ts-jest', ...]两条规则。
旧式字符串 preset(如ts-jest/presets/default、ts-jest/presets/js-with-ts等)仍可使用,但官方明确警告:ts-jest 不推荐使用 legacy preset,因为这种方式不利于灵活配置 Jest,且会在下个大版本中移除,用户被强烈建议迁移到上述函数式写法。
底层处理流程:从源文件到可执行代码
如果你关心 ts-jest 内部到底做了什么,仓库内部文档 website/docs/processing.md 给出了完整的处理流程(该文档定位为贡献者内部文档)。结合 src/legacy/ts-jest-transformer.ts 的实现,整个转换链路可以概括为:
- 入口
tsJest.process(source):Jest 调用 transformer 的process方法,传入源文件内容与转换配置。 - 可选的字符串化:若命中
stringifyContentPathRegex,文件内容会被 JSON 序列化为模块(常用于把.json、模板等文件直接变成返回自身内容的模块)。 .d.ts声明文件直接清空内容:定义文件无需编译,直接产出空内容。- 编译器选择:若未开启隔离模块,则创建并缓存 TypeScript Language Service,以"项目"上下文编译;若开启,则逐文件用
transpileModule独立编译。 - 持久缓存检查:命中持久缓存则直接恢复内存缓存,否则执行编译。
- 自定义 AST transformers:在这里执行
jest.mock的提升(hoisting)以及用户基于配置定义的 AST 转换(对应astTransformers选项)。 - 修复 Source Map:对编译产物修正 Source Map,更新内存缓存与持久缓存。
- 可选 Babel 二次处理:若配置了
babelConfig,调用babel-jest的 process 再次转换。 afterProcess钩子:若存在该钩子且返回了内容,则以其返回值作为新源码。
从 src/legacy/ts-jest-transformer.ts 可以看到,TsJestTransformer实现了 Jest 的SyncTransformer,并通过静态缓存_cachedConfigSets在不同测试运行之间复用ConfigSet与编译器实例,这正是 ts-jest 在 watch 模式下依然能保持较快编译速度的实现基础。
版本策略与注意事项
ts-jest不采用语义化版本(SemVer)。官方在 website/docs/introduction.md 中特别强调:
我们不进行语义化版本管理,
23.10是一次重写。运行npm i -D ts-jest@"<23.10.0"可以回退到之前的版本。
这意味着从旧版本升级到23.10及以上时,需要留意可能的行为变化;如果需要兼容旧行为,可以用上面的命令锁定<23.10.0版本。项目主版本号跟随 Jest 的主版本,但整体版本策略并非严格 SemVer(详见 README.md 的 Versioning 一节)。
另外,website/docs/getting-started/version-checking.md 记载了一个已被标记 DEPRECATED 的版本检查机制:ts-jest 默认支持一个范围的 jest/typescript 版本,使用不兼容版本时会收到警告,可通过设置环境变量TS_JEST_DISABLE_VER_CHECKER=true关闭(Linux/macOS 用export,Windows 用set)。该机制已废弃,未来将由package.json中原生的peerDependencies检查取代。
TypeScript 7 用户的特别说明
如果你的项目使用 TypeScript 7,官方建议采用并排编译器方案(详见 website/docs/guides/typescript-7.md):TypeScript 7.0 自带原生tsc,但不提供 ts-jest 转换所需的 JavaScript 编译器 API。应通过 npm 别名同时安装两个编译器:
npm install --save-dev '@typescript/native@npm:typescript@^7.0.2' 'typescript@npm:@typescript/typescript6@^6.0.2'这样npx tsc运行原生 TypeScript 7 编译器,而 ts-jest 通过typescript别名获得其需要的 TypeScript 6 JavaScript API。不要将 ts-jest 的compiler选项指向@typescript/native,因为 TypeScript 7.0 没有兼容的 JavaScript API,ts-jest 会在加载该包时提前停止并给出可操作的配置错误。
小结
ts-jest 以"带 Source Map 支持的 Jest transformer"为定位,提供了 Babel 方案所不具备的完整类型检查与全部 TypeScript 特性支持。通过本文你可以:
- 理解 ts-jest 与 Babel7 +
@babel/preset-typescript的取舍(类型检查、namespace、const enum、声明合并、legacy 导入导出、JSX 下尖括号断言等); - 按速查表完成安装、
config:init配置与测试运行; - 掌握
tsconfig、isolatedModules、diagnostics、astTransformers等核心选项及其默认行为; - 了解底层编译流程与缓存机制,为性能调优和问题排查打基础;
- 明确非 SemVer 版本策略与 TypeScript 7 的并排安装方案。
需要继续深入时,可依次阅读仓库中的 website/docs/getting-started/installation.md、website/docs/getting-started/options.md、website/docs/getting-started/presets.md 以及 website/docs/processing.md,并结合 src/legacy/ts-jest-transformer.ts 与 src/presets/create-jest-preset.ts 阅读源码实现。
- 测试
- 开发工具
【免费下载链接】ts-jest
A Jest transformer with source map support that lets you use Jest to test projects written in TypeScript.
相关推荐
掌握RecyclerViewAnimators4cq Controller的7个配置方法:duration/firstOnly/偏移参数完整参考
掌握RecyclerViewAnimators4cq Controller的7个配置方法:duration/firstOnly/偏移参数完整参考 Recycle
测试开发工具ts-jest 入门指南:用 Jest 测试 TypeScript 项目的 Transformer 配置与实践
ts jest 入门指南:用 Jest 测试 TypeScript 项目的 Transformer 配置与实践 ts jest 是一个带源码映射(source
测试开发工具UE4SS终极指南:10分钟解锁虚幻引擎游戏无限可能
UE4SS终极指南:10分钟解锁虚幻引擎游戏无限可能 还在为虚幻引擎游戏的Mod安装而烦恼吗?每次看到精彩的游戏修改内容,却因为复杂的安装流程而望而却步?今天,
游戏开发逆向工程
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考