How to type an array of Promises of various types in TS?

Advertisements

Given two promises – one that needs to be executed every time and one that needs to be executed only if a condition is met – that I want to execute asynchronously, how do I ensure that return type of Promise.all for each value is correct?

Here’s an implementation that I thought should work:

type Promises = [Promise<string>, Promise<number>?]

const promises: Promises = [Promise.resolve('Lorem')]

if (someCondition) {
  promises.push(Promise.resolve(1))
}

// 'resolvedString' should be string
// 'resolvedNumber' should be number | undefined
const [resolvedString, resolvedNumber] = await Promise.all(promises)

but there are two issues with this code:

  • Value of resolvedNumber is number and not number | undefined according to VSCode

  • TS doesn’t compile because of following error:

  The last overload gave the following error.
    Argument of type 'Promises' is not assignable to parameter of type 'Iterable<string | PromiseLike<string>>'.
      The types returned by '[Symbol.iterator]().next(...)' are incompatible between these types.
        Type 'IteratorResult<Promise<string> | Promise<number>, any>' is not assignable to type 'IteratorResult<string | PromiseLike<string>, any>'.
          Type 'IteratorYieldResult<Promise<string> | Promise<number>>' is not assignable to type 'IteratorResult<string | PromiseLike<string>, any>'.
            Type 'IteratorYieldResult<Promise<string> | Promise<number>>' is not assignable to type 'IteratorYieldResult<string | PromiseLike<string>>'.
              Type 'Promise<string> | Promise<number>' is not assignable to type 'string | PromiseLike<string>'.
                Type 'Promise<number>' is not assignable to type 'string | PromiseLike<string>'.
                  Type 'Promise<number>' is not assignable to type 'PromiseLike<string>'.
                    Types of property 'then' are incompatible.
                      Type '<TResult1 = number, TResult2 = never>(onfulfilled?: (value: number) => TResult1 | PromiseLike<TResult1>, onrejected?: (reason: any) => TResult2 | PromiseLike<TResult2>) => Promise<...>' is not assignable to type '<TResult1 = string, TResult2 = never>(onfulfilled?: (value: string) => TResult1 | PromiseLike<TResult1>, onrejected?: (reason: any) => TResult2 | PromiseLike<TResult2>) => PromiseLike<...>'.
                        Types of parameters 'onfulfilled' and 'onfulfilled' are incompatible.
                          Types of parameters 'value' and 'value' are incompatible.
                            Type 'number' is not assignable to type 'string'.

93           const [resolvedString, resolvedNumber] = await Promise.all(promises)

TypeScript version is 4.3.5

>Solution :

This is a bug/feature that has been fixed on TS 4.5.

Leave a ReplyCancel reply