Property 'allSettled' does not exist on type 'PromiseConstructor'.ts(2339)
JavascriptTypescriptEs6 PromiseJavascript Problem Overview
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.
Javascript Solutions
Solution 1 - Javascript
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}>>;
}
Solution 2 - Javascript
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);
Solution 3 - Javascript
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 [email protected]
woot woot!
Solution 4 - Javascript
Workaround to use it with older Typescript version
await (Promise as any).allSettled(promises);
Solution 5 - Javascript
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>[]>;
}
}