【问题标题】:Property 'allSettled' does not exist on type 'PromiseConstructor'.ts(2339)类型“PromiseConstructor”.ts(2339) 上不存在属性“allSettled”
【发布时间】:2020-06-02 04:27:54
【问题描述】:

我正在尝试将 Promise.allSettled API 与 TypeScript 一起使用。代码在这里:

server.test.ts:

it('should partial success if QPS > 50', async () => {
  const requests: any[] = [];
  for (let i = 0; i < 51; i++) {
    requests.push(rp('http://localhost:3000/place'));
  }
  await Promise.allSettled(requests);
  // ...
});

但是 TSC 抛出错误:

类型“PromiseConstructor”.ts(2339) 上不存在属性“allSettled”

我已经将这些值添加到tsconfig.json 中的lib 选项中:

tsconfig.json:

{
  "compilerOptions": {
    /* Basic Options */
    "target": "ES2015" /* Specify ECMAScript target version: 'ES3' (default), 'ES5', 'ES2015', 'ES2016', 'ES2017','ES2018' or 'ESNEXT'. */,
    "module": "commonjs" /* Specify module code generation: 'none', 'commonjs', 'amd', 'system', 'umd', 'es2015', or 'ESNext'. */,
    "lib": [
      "ES2015",
      "ES2016",
      "ES2017",
      "ES2018",
      "ES2019",
      "ES2020",
      "ESNext"
    ] 
   // ...
}

TypeScript 版本:"typescript": "^3.7.3"

那么,我该如何解决呢?我知道我可以使用替代模块,但我对原生使用 TypeScript 感到好奇。

【问题讨论】:

    标签: javascript typescript es6-promise


    【解决方案1】:

    对我有用的是简单地将“es2020”添加到 tsconfig.json 文件的“lib”属性中

    【讨论】:

      【解决方案2】:

      有一个可用的 shim 库提供相同的功能 (https://www.npmjs.com/package/promise.allsettled),但请注意,它需要显式导入 (var allSettled = require('promise.allsettled');)。

      如果你在 typescript 中工作,等效的 typed 包是 https://www.npmjs.com/package/@types/promise.allsettled,但请注意类型名称与官方 ES2020 实现不匹配,所以如果你想要一个精确的 drop-in 替换,你需要添加一个新的 TS 文件为类型设置别名并在全局命名空间中可用:

      import { PromiseRejection, PromiseResolution, PromiseResult } from 'promise.allsettled';
      
      // https://stackoverflow.com/a/59499895/323177
      export {}
      
      // TechDebt: Remove once project is migrated to ES2020
      // Global type aliases are required because the promise.allsettled shim doesn't match the types of the actual 
      // ES2020 implementation
      declare global {
          export type PromiseFulfilledResult<T> = PromiseResolution<T>;
          
          export type PromiseRejectedResult = PromiseRejection<any>;
          
          export type PromiseSettledResult<T> = PromiseResult<T, any>;
      
          export class PromiseConstructor {
              /**
               * Creates a Promise that is resolved with an array of results when all
               * of the provided Promises resolve or reject.
               * @param values An array of Promises.
               * @returns A new Promise.
               */
               allSettled<T extends readonly unknown[] | readonly [unknown]>(values: T):
                   Promise<{ -readonly [P in keyof T]: PromiseSettledResult<T[P] extends PromiseLike<infer U> ? U : T[P]> }>;
      
              /**
               * Creates a Promise that is resolved with an array of results when all
               * of the provided Promises resolve or reject.
               * @param values An array of Promises.
               * @returns A new Promise.
               */
              allSettled<T>(values: Iterable<T>): Promise<PromiseSettledResult<T extends PromiseLike<infer U> ? U : T>[]>;
          }
      }
      

      【讨论】:

        【解决方案3】:

        要让它在 Linux 上运行,我需要最新的 typescript 版本:

        npm install -g typescript@latest
        

        然后在您的 tsconfig 中,您当前需要 ES2020.Promise 库。我的完整 tsconfig:

        {
          "compilerOptions": {
            "sourceMap": true,
            "module": "commonjs",
            "target": "es5",
            "jsx": "react",
            "esModuleInterop": true,
            "allowJs": true,
            "outDir": "./dist",
            "lib": [
              "ES2020.Promise",
            ]
          },
          "include": [
            "./src"
          ],
          "exclude": [
            "./node_modules",
            "./build"
          ],
          "compileOnSave": true,
          "parserOptions": {
            "ecmaFeatures": {
              "jsx": true
            }
          }
        }
        

        用法:const results = await Promise.allSettled(BatchOfPromises);

        【讨论】:

          【解决方案4】:

          将它与旧版 Typescript 一起使用的解决方法

          await (Promise as any).allSettled(promises);
          

          【讨论】:

          • 最直接的单行答案!
          • 如果没有必要,不要这样做。
          • 这是一个让 TS 编译器通过的 hack。相反,您应该使用诸如npmjs.com/package/@types/promise.allsettled 之类的 shim 库来避免修改生产代码
          【解决方案5】:

          它是 ES2020 并且处于第 4 阶段,因此如果没有 polyfill,则无法在任何地方使用。它被输入并合并到TS。尝试安装最新的 @types/node 包,看看是否能将其拉入。

          更新:看起来它会在它登陆时将es2020.promise 添加到库中。

          更新:npm i typescript@3.8.0-betawoot woot!

          【讨论】:

            【解决方案6】:

            The types for Promise.allSettled() 仅在 1 月份合并,显然将在 TypeScript 3.8 中发布。

            作为临时解决方案,您可以自己为函数声明一个模拟类型:

            declare interface PromiseConstructor {
                allSettled(promises: Array<Promise<any>>): Promise<Array<{status: 'fulfilled' | 'rejected', value?: any, reason?: any}>>;
            }
            

            【讨论】:

            • 你怎么知道它什么时候发布?
            • @JoshWulf 查看该提交的标签,您可以看到它们适用于 3.8。一些谷歌搜索可以带你到 github.com/microsoft/TypeScript/issues/34898 显示时间表
            • 我在 3.9.5 还是没有这种类型,是不是我的环境有问题?
            • @oskar132 确保您的tsconfig.jsonlib 数组中具有es2020
            • tsconfig.json改成es2020后,我不得不关闭并重新打开VSCode,但它可以工作。谢谢@jmzagorski!
            猜你喜欢
            • 2021-01-10
            • 2019-08-11
            • 2021-08-02
            • 2022-07-09
            • 2022-10-04
            • 2023-02-07
            • 2020-08-23
            • 2021-12-19
            • 2020-07-16
            相关资源
            最近更新 更多