Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to use promise.allSettled with typescript?

Typescript build is failing as it does not seem to like Promise.allSetttled even though I have set ts config comilerOptions with "lib": [ "ES2020.Promise" ],

It seems as though the response for promise.allSettled does not include result or reason.

When running typescript build I get the following error:

Property 'reason' does not exist on type 'PromiseSettledResult<IMyPromiseResult>'.

and

Property 'value' does not exist on type 'PromiseRejectedResult'.

My code block looks like this and as you can see, I am trying to access reason and result from eaech of the promises that get resolved.

const myPromise = async () : Promise<IMyPromiseResult> {
  return new Promise((resolve) => {
    resolve("hello world")
  })
}

const data = await Promise.allSettled([
  myPromise()
]);

const response = data.find(res => res.status === 'fulfilled')?.result;

if(!response) {
  const error = data.find(res => res.status === 'rejected')?.reason;
  throw new Error(error);
}

How can I update the Promise.allSettled declaration to include the correct interfaces?

like image 886
Stretch0 Avatar asked Nov 20 '20 10:11

Stretch0


People also ask

Can we use promise in TypeScript?

Introduction to TypeScript promise. The promise in TypeScript is used to make asynchronous programming. The promise can be used when we want to handle multiple tasks at the same time. By the use of TypeScript promise, we can skip the current operation and move to the next line of the code.

How does promise allSettled work?

The Promise. allSettled() method returns a promise that fulfills after all of the given promises have either fulfilled or rejected, with an array of objects that each describes the outcome of each promise.

How do you define a promise type in TypeScript?

To declare a function with a promise return type, set the return type of the function to a promise right after the function's parameter list, e.g. function getPromise(): Promise<number> {} . If the return type of the function is not set, TypeScript will infer it. Copied!


2 Answers

Like Bergi mentioned TypeScript does not know if the type is PromiseFulfilledResult / PromiseRejectedResult when checking types.

The only way is to cast the promise result. This can be done because you already verified that the resolved promise is either fulfilled or rejected.

See this example:

const myPromise = async (): Promise<string> => {
  return new Promise((resolve) => {
    resolve("hello world");
  });
};

const data = await Promise.allSettled([myPromise()]);

const response = (data.find(
  (res) => res.status === "fulfilled"
) as PromiseFulfilledResult<string> | undefined)?.value;

if (!response) {
  const error = (data.find(
    (res) => res.status === "rejected"
  ) as PromiseRejectedResult | undefined)?.reason;
  throw new Error(error);
}
like image 123
Jens Avatar answered Sep 21 '22 15:09

Jens


Like bela53 stated, use type guards. A more elegant solution than to inline the type guards is to define them as separate functions, and with generics binding you'd get the correct value too for the fulfilled promises, and can reuse for any allSettled filtering needs.

Casting is not needed (and generally should be avoided).

const isRejected = (input: PromiseSettledResult<unknown>): input is PromiseRejectedResult => 
  input.status === 'rejected'

const isFulfilled = <T>(input: PromiseSettledResult<T>): input is PromiseFulfilledResult<T> => 
  input.status === 'fulfilled'

const myPromise = async () => Promise.resolve("hello world");

const data = await Promise.allSettled([myPromise()]);

const response = data.find(isFulfilled)?.value
const error = data.find(isRejected)?.reason
like image 39
vesse Avatar answered Sep 21 '22 15:09

vesse