jestjs - 为什么在 Jest 中运行时 for..of 循环在 Iterables 上不起作用?
问题描述
我有以下打字稿代码:
const myMap = new Map([["name", 5]]);
for (const foo of myMap.values()) {
console.log(foo);
}
当我直接在节点(v8.12.0)中运行此代码时,它可以工作并将“5”打印到控制台。
如果我在 Jest 测试中运行完全相同的代码,它永远不会执行 for 循环的内容。它运行 for 条件,然后跳过循环,从不实际枚举值。
这是为什么?Jest 使用的 JS 运行时(不是节点吗?)有什么不支持 for..of over iterables 的吗?
谢谢!
解决方案
经过很长时间的调查,我已经了解了这一点。关于解决方案的重要背景信息:
- 当使用 TypeScript 编译器针对较旧的 ECMAscript 版本(如 ES3 和 ES5 )时,默认情况下不支持使用
for..of
循环来迭代集合。Iterable
如果你想使用for..of
withIterable
,你必须定位比 ES5 更新的东西,或者使用--downlevelIteration flag
. - 要将 Jest 与 TypeScript 项目一起使用,请使用ts-jest。至少,我是。我认为您也可以以某种方式使用 babel,但我认为 ts-jest 是首选。
- 使用 ts-jest 时,默认情况下它会尝试使用项目使用的 tsconfig.json 文件——据我所知,这意味着您正在使用的 jest.config.js 文件旁边的那个(或当前目录,如果您没有指定 jest.config.js 文件)。如果在项目目录中找不到 tsconfig.json 文件,它会使用默认的 TypeScript 编译器选项。默认编译器选项导致 TypeScript 编译器以 ES3 或 ES5 为目标(ts-jest 文档声称它默认为 ES3,但在这种情况下 ts-jest 会覆盖默认值为 ES5)。
--downlevelIteration
默认情况下未启用。
考虑到这一切,我发现 ts-jest 无法找到我的项目的 tsconfig.json 文件,因此它使用默认设置运行我的测试,这意味着针对 ES5 而不允许downlevelIteration
,所以我所有的for..of
循环Iterable
不起作用。它找不到我的 tsconfig.json 文件的原因是因为我的 jest.config.js 文件位于不同的目录中(在树中较高的位置),即使我是从带有 tsconfig.json 文件的目录运行 jest, ts-jest 没有在“当前”目录中查找,而是在我为 jest.config.js 文件指向 jest 的目录中查找,该文件不包含 tsconfig.json。
我对此的解决方案是稍微修改我的目录结构并利用ts-jest的 tsConfig 选项告诉它在哪里可以找到我的 tsconfig.json 文件,这使得一切“神奇”地工作,因为我的 tsconfig.json 文件针对 es2018,它支持for..of
迭代Iterable
。
我考虑过但很快被忽略的另一种解决方案是上述 tsConfig 设置的功能,可直接--downlevelIteration
在 jest 配置中设置编译器选项。我选择不这样做是因为,虽然它可以解决这个特定问题,但它不会解决更大的问题,即我的 Jest 测试使用与生产代码不同的标志编译我的 TypeScript!碰巧的是,由此引起的唯一当前问题是我的for..of
循环痛苦。
一个简短的后记:我最终在这个问题上取得进展的方式是偶然发现 ts-jest 中的诊断选项。将其设置为 true 后,当我尝试运行测试时,会显示如下错误:
TypeScript diagnostics (customize using [jest-config].globals.ts-jest.diagnostics option): src/foo.ts:163:47 - error TS2569: Type 'Map<Guid, FooInfo>' is not an array type or a string type. Use compiler option '--downlevelIteration' to allow iterating of iterators.
似乎应该显示 TS 编译器错误(并导致测试失败),无论是否启用 ts-jest“诊断”但shrug。
推荐阅读
- javascript - 如何使购物车的数据动态增加?
- reactjs - 如何在浏览器 ReactJS 中更改桌面视图、平板电脑视图、移动视图
- python - 如何在 Python 中比较 2 个字典值并通过键与常用值配对?
- docker - 错误:无法使用前端 dockerfile.v0 解决:无法创建 LLB 定义:构建 docker 映像时清单中的平台不匹配
- git - Git 工作流程二:拆分 1 个 PR 拆分为 2 个 PR
- react-native - 如何在功能组件中使用recyclerlistview
- python - 如何通过 Django 视图中的 QuerySet 过滤器访问 Django 模型的属性属性?
- yaml - 是否可以在 startagy 矩阵 github 动作中给出动态值?
- ansible - Ansible:使用 group_vars/all/FILE.yaml 作为默认值
- java - java String 方法中的“toffset”和“ooffset”分别代表什么:regionMatches(int toffset, String other, int ooffset, int len)?