54

I'm trying to use the Promise.allSettled API with TypeScript. Code here:

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);
  // ...
});

But TSC throws an error:

Property 'allSettled' does not exist on type 'PromiseConstructor'.ts(2339)

I already added these values to the lib option in tsconfig.json:

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 version: "typescript": "^3.7.3"

So, how can I solve this? I know I can use an alternative module, but I am curious about working with TypeScript natively.

Pang
  • 9,564
  • 146
  • 81
  • 122
Lin Du
  • 88,126
  • 95
  • 281
  • 483

7 Answers7

45

The types for Promise.allSettled() were only merged in January, and will apparently be released in TypeScript 3.8.

As an interim solution, you can declare a mock-ish type for the function yourself:

declare interface PromiseConstructor {
    allSettled(promises: Array<Promise<any>>): Promise<Array<{status: 'fulfilled' | 'rejected', value?: any, reason?: any}>>;
}
AKX
  • 152,115
  • 15
  • 115
  • 172
23

To get this running on Linux, I needed the latest typescript version:

npm install -g typescript@latest

Then in your tsconfig you currently need the ES2020.Promise lib. My full 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
    }
  }
}

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

Leigh Mathieson
  • 1,658
  • 2
  • 17
  • 25
11

It's ES2020 and at Stage 4, so not available everywhere without a polyfill. It got typed and merged into TS. Try installing the latest @types/node package and see if that pulls it in.

Update: Looks like it will be adding es2020.promise to the libs, when it does land.

Update: npm i typescript@3.8.0-beta woot woot!

Josh Wulf
  • 4,727
  • 2
  • 20
  • 34
11

Workaround to use it with older Typescript version

await (Promise as any).allSettled(promises);
Devil Sparrow
  • 151
  • 1
  • 2
5

What worked for me was to simply add "es2020" into the "lib" attribute of tsconfig.json file

tsconfig.json file with the value "es2020" included in the "lib" attribute; "lib" attribute is circled in red

Henry Ecker
  • 34,399
  • 18
  • 41
  • 57
Ramón Espinosa
  • 151
  • 2
  • 4
2

There is a shim library available that provides identical functionality (https://www.npmjs.com/package/promise.allsettled), but note that it requires an explicit import (var allSettled = require('promise.allsettled');).

If you are working in typescript, the equivalent typed package is https://www.npmjs.com/package/@types/promise.allsettled, but note that the type names do not match the official ES2020 implementation, so if you want an exact drop-in replacement, you will need to add a new TS file to alias the types and make available in the global namespace:

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>[]>;
    }
}
Woodz
  • 1,029
  • 10
  • 24
0

@types/node needs to be updated

A working version is here:

npm i @types/node@17.0.33

You can see versions from here

Murat Colyaran
  • 2,075
  • 2
  • 8
  • 27