I've been trying to use Promise.allSettled on NodeJS with Typescript recently, and I'm facing issues with the response. the allSettled method returns an array with status: "rejected" | "fulfilled"
and a value, in case it's fulfilled. The problem is, when I try to access the value of the response, I get the following errors:
Property 'value' does not exist on type 'PromiseSettledResult<unknown>'.
Property 'value' does not exist on type 'PromiseRejectedResult'.ts(2339)
Below I'll leave a simple example so you can copy the code and try yourself:
const p1 = Promise.resolve(50);
const p2 = Promise.resolve(100);
const promiseArray = [p1, p2];
Promise.allSettled( promiseArray ).
then( results => results.forEach( result =>
console.log(result.status, result.value)));
If I run this code on my project, I get an error because of result.value
at the end.
I'm running my node on version 12.18.3 on Windows, and I've set my target on the tsconfig.json
as ES2020
to be able to use the method itself.
Got same error in case of filter promises array:
const promises = ids.map((id) => <some BE API call>);
const resolvedPromises = await Promise.allSettled(promises);
resolvedPromises.filter(({ status }) => status === 'fulfilled').map((p) => p.value);
Error screenshot
The problem is allSettled
returns PromiseSettledResult
, which is not exported at all (I use lib.es2020.promise in tsconfig
):
interface PromiseFulfilledResult<T> {
status: "fulfilled";
value: T;
}
interface PromiseRejectedResult {
status: "rejected";
reason: any;
}
type PromiseSettledResult<T> = PromiseFulfilledResult<T> | PromiseRejectedResult;
and .map
doesn't understand that all rejected
promises were filtered in filtered
method.
So, I even can't import types and cast values to them.
As a temporary solution I suppressed ESLint and TSC rules with comments:
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-ignore
Then I created same to PromiseFulfilledResult
interface in the project and used types casting:
resolvedPromises.filter(({ status }) => status === 'fulfilled').map((p) => (p as PromiseFulfilledResult).value);
As a result I got rid of on error and ESLint/TS rules ignoring comments.
@jonrsharpe answered it: You only have a value attribute where the status is fulfilled, and you're not checking for that.
So using my own example, it can be fixed as the following:
const p1 = Promise.resolve(50);
const p2 = Promise.resolve(100);
const promiseArray = [p1, p2];
Promise.allSettled( promiseArray ).
then( results => results.forEach( result =>
console.log(result.status,
result.status === 'fulfilled' && result.value
);
));
It now verifies if the promise was fulfilled and then prints the value, if it's the case.
You can avoid this error if you make a type statement after calling the allSettled
method. For example, you can immediately enter a type for typescript as follows:
const promises = await Promise.allSettled([
fetch(url).then((response) => response.json()),
fetch(url).then((response) => response.json()),
]) as {status: 'fulfilled' | 'rejected', value: SomeType}[];
After that it will work correctly:
const resolvedPromises = promises.filter(({ status }) => status === 'fulfilled');
const responses = resolvedPromises.map((promise) => promise.value);
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With