TS Jest 不会接受 NodeJS 16 和 TypeScript 的顶级等待

gal*_*h92 25 node.js typescript jestjs top-level-await

我正在尝试将我的 NodeJS 12 和 TypeScript 应用程序更新到 Node16,原因之一是需要使用顶级等待。

\n

更新后代码可以正确编译,但 Jest 不会接受特定的顶级等待代码:

\n
ts-jest[ts-compiler] (WARN) src/xxx.ts:11:17 - error TS1378: Top-level \'await\' expressions are only allowed when the \'module\' option is set to \'es2022\', \'esnext\', \'system\', or \'nodenext\', and the \'target\' option is set to \'es2017\' or higher.\n\n11 const project = await client.getProjectId();\n                   ~~~~~\n FAIL  src/xxx.test.ts\n  \xe2\x97\x8f Test suite failed to run\n\n    Jest encountered an unexpected token\n
Run Code Online (Sandbox Code Playgroud)\n

包.json:

\n
ts-jest[ts-compiler] (WARN) src/xxx.ts:11:17 - error TS1378: Top-level \'await\' expressions are only allowed when the \'module\' option is set to \'es2022\', \'esnext\', \'system\', or \'nodenext\', and the \'target\' option is set to \'es2017\' or higher.\n\n11 const project = await client.getProjectId();\n                   ~~~~~\n FAIL  src/xxx.test.ts\n  \xe2\x97\x8f Test suite failed to run\n\n    Jest encountered an unexpected token\n
Run Code Online (Sandbox Code Playgroud)\n

tsconfig.json:

\n
{\n  "compilerOptions": {\n    "module": "es2022",\n    "noImplicitReturns": true,\n    "noUnusedLocals": true,\n    "outDir": "lib",\n    "sourceMap": false,\n    "strict": true,\n    "target": "es2021",\n    "moduleResolution": "Node",\n    "resolveJsonModule": true\n  },\n  "compileOnSave": true,\n  "include": [\n    "src"\n  ],\n  "ts-node": {\n    "moduleTypes": {\n      "jest.config.ts": "cjs"\n    }\n  }\n}\n
Run Code Online (Sandbox Code Playgroud)\n

笑话.config.ts:

\n
export default {\n  roots: [\n    \'<rootDir>/src\'\n  ],\n  setupFiles: [\'./src/setupJestEnv.ts\'],\n  preset: \'ts-jest\',\n  testEnvironment: \'node\',\n  testPathIgnorePatterns: [\'/node_modules/\'],\n  coverageDirectory: \'./coverage\',\n  coveragePathIgnorePatterns: [\'node_modules\', \'src/database\', \'src/test\', \'src/types\'],\n  globals: { \'ts-jest\': { diagnostics: false } },\n};\n
Run Code Online (Sandbox Code Playgroud)\n

我真的不明白这里出了什么问题。任何想法?

\n

Mar*_*ara 10

经过一些研究,我当然可以告诉你,我们距离可靠的解决方案还很远。主要问题是顶层await可用

\n
\n

当“module”选项设置为“es2022”、“esnext”、“system”或“nodenext”,并且“target”选项设置为“es2017”时\' 或更高。

\n
\n

即使您在 中设置了module和,您也必须理解并解决很多错误,正如您所经历的那样。我刚刚找到了一个适合我的配置,但它可能会带来我不知道的其他问题。targetes2022tsconfig.json

\n
\n
$ node --version\nv17.7.2\n$ npm list\nmyproject@1.0.0 /home/me/folder\n\xe2\x94\x9c\xe2\x94\x80\xe2\x94\x80 @types/jest@27.4.1\n\xe2\x94\x9c\xe2\x94\x80\xe2\x94\x80 @types/node@17.0.25\n\xe2\x94\x9c\xe2\x94\x80\xe2\x94\x80 config@3.3.7\n\xe2\x94\x9c\xe2\x94\x80\xe2\x94\x80 jest@27.5.1\n\xe2\x94\x9c\xe2\x94\x80\xe2\x94\x80 sequelize@6.18.0\n\xe2\x94\x9c\xe2\x94\x80\xe2\x94\x80 timespan@2.3.0\n\xe2\x94\x9c\xe2\x94\x80\xe2\x94\x80 ts-jest@27.1.4\n\xe2\x94\x9c\xe2\x94\x80\xe2\x94\x80 ts-node@10.7.0\n\xe2\x94\x9c\xe2\x94\x80\xe2\x94\x80 ...\n\xe2\x94\x94\xe2\x94\x80\xe2\x94\x80 typescript@4.6.3\n
Run Code Online (Sandbox Code Playgroud)\n

我还有其他库,但不需要重新调整它们。我用于jest测试和sequelizeORM:它们需要进行适当的配置。让我们从package.json

\n
{\n    "type": "module",\n    "scripts": {\n        "prestart": "npx tsc",\n        "start": "NODE_ENV=production node --es-module-specifier-resolution=node out/index.js",\n        "test": "node --no-warnings --experimental-vm-modules node_modules/jest/bin/jest.js tests/"\n    },\n    ...\n}\n
Run Code Online (Sandbox Code Playgroud)\n
    \n
  • "type": "module"在这里解释
  • \n
  • start本节中的命令需要scripts选项--es-module-specifier-resolution=node,这是启用 ES 模块而不是默认 CommonJS 模块所必需的。
  • \n
  • (仅适用于 Jest)--no-warnings不是强制性的,但--experimental-vm-modules确实如此。
  • \n
\n
\n

至于 Jest 配置:

\n
$ cat jest.config.ts\nimport type { Config } from \'@jest/types\';\n\nconst config: Config.InitialOptions = {\n    globals: {\n        "ts-jest": {\n            useESM: true\n        }\n    },\n    preset: \'ts-jest/presets/default-esm\',\n    roots: ["tests/"],\n    modulePathIgnorePatterns: [\n        "<rootDir>/node_modules/"\n    ]\n};\n\nexport default config;\n
Run Code Online (Sandbox Code Playgroud)\n

当然,您可以添加新属性,但这或多或少是最低配置。您可以在此处找到其他预设(如果您需要它们),而 的globals部分将在此处ts-jest进一步说明

\n
\n

让我们看看tsconfig.json,它有点复杂:

\n
$ cat tsconfig.json\n{\n    "ts-node": {\n        "moduleTypes": {\n            "jest.config.ts": "cjs"\n        }\n    },\n    "compilerOptions": {\n        "lib": ["ES2021"],\n        "module": "ESNext",\n        "esModuleInterop": true,\n        "moduleResolution": "node",\n        "target": "ESNext",\n        "outDir": "out",\n        "resolveJsonModule": true\n    },\n    "compileOnSave": true,\n    "include": ["src/"],\n    "exclude": ["node_modules", "**/*.spec.ts"]\n}\n
Run Code Online (Sandbox Code Playgroud)\n

同样,它或多或少是最小配置,我猜想module属性target可以使用尝试使用 top-level 时显示的错误中的其他替代方案进行初始化await,但我不确定它们是否都有效。

\n
\n

现在最糟糕的部分是软件包与 ES 模块的兼容性。我还没有进行足够的研究来告诉您何时import需要调整某个包中的某个包,但我将为您提供一些示例。

\n

内置库config//timespan

\n

内置库应该没问题。在我的项目中,我还使用configtimespan

\n
    \n
  • timespanimport * as timespan from "timespan": 。该Timespan对象可以使用new timespan.Timespan(...)例如访问。
  • \n
  • configimport config from \'config\': 。
  • \n
  • util:使用内置包,我认为您可以导入任何导出的函数,就像使用 CommonJS 语法一样。例如,import { format } from \'util\'
  • \n
\n

sequelize(还有许多其他人......)

\n

我正在使用sequelize打字稿,但我必须更改import语法。我遇到的错误是:

\n
\n

SyntaxError:请求的模块“sequelize”不提供名为“DataTypes”的导出...

\n
\n

问题是实验模块不支持命名导出。新import语法取决于您需要导入的内容:

\n
    \n
  • 对于类型,您仍然可以像以前一样导入它们,例如import { Type1, Type2 } from \'your_library\'
  • \n
  • 对于类(但我认为一切都来自值空间),您首先需要导入一个默认对象,然后使用对象解构来提取所需的值。
  • \n
\n

例如,使用sequelize

\n
import Sequelize, \n    { InferAttributes, InferCreationAttributes, CreationOptional }\n    from \'sequelize\';                         // InferAttributes, InferCreationAttributes, CreationOptional are types \nconst { Op, DataTypes, Model } = Sequelize    // these are classes\n\nclass UserModel extends Model<InferAttributes<UserModel>, \n    InferCreationAttributes<UserModel>> \n{\n    declare id: CreationOptional<number>\n    ...\n}\n
Run Code Online (Sandbox Code Playgroud)\n
\n

其他来源

\n\n