为什么在 Jest 中运行时 for..of 循环对 Iterables 不起作用?

Aut*_*ant 3 jestjs

我有以下打字稿代码:

const myMap = new Map([["name", 5]]);
for (const foo of myMap.values()) {
    console.log(foo);
}
Run Code Online (Sandbox Code Playgroud)

当我直接在 node (v8.12.0) 中运行此代码时,它会工作并将“5”打印到控制台。

如果我在 Jest 测试中运行完全相同的代码,它永远不会执行 for 循环的内容。它运行 for 条件,然后跳过循环,从不实际枚举值。

这是为什么?是否有关于 Jest 使用的 JS 运行时(不是节点吗?)不支持..of over iterables?

谢谢!

Aut*_*ant 7

经过很长时间的调查,我已经找到了这个问题的根源。有关解决方案的重要背景信息:

  1. 当使用 TypeScript 编译器面向较旧的 ECMAscript 版本(如 ES3 和 ES5)时,默认情况下不支持使用for..of循环来迭代Iterable集合。如果要使用for..ofwith Iterable,则必须针对比 ES5 更新的内容或使用--downlevelIteration flag.
  2. 要在 TypeScript 项目中使用 Jest,请使用ts-jest。至少,我是。我认为你也可以以某种方式使用 babel 但我认为 ts-jest 是首选
  3. 使用 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-jest“诊断”但shrug,似乎都应该显示 TS 编译器错误(并导致测试失败)。