beraliv

Promise.all types under the hood in TypeScript

Example of Promise.all use
Example of Promise.all use

Today we discuss Promise.all

This is helpful in case we need to wait for all the values (e.g. we pass [Promise<number>, 42, Promise<string>] and expect to have Promise<[number, 42, string]> at the end).

Let's solve it 🚀

Iteration over tuple elements

Previously, one of the challenges in easy category was Unwrapping the Promises where we imitated await in types:

Awaited solution
Awaited solution

This will help to iterate over tuple elements and replace Promise with the resolved type.

We already know how to iterate over tuple elements with Making object out of tuple but here we have the difference:

  1. If we want to have elements of tuple inside the object type, we use Mapped Types:
Tuple in object type
Tuple in object type
  1. If we need to work with tuple elements and leave the structure as is, we use Type inference in conditional types with Rest elements in Tuples:
Tuple in tuple
Tuple in tuple

As we need to transform the elements inside the tuple but still need to have the tuple at the end, we will use the second approach. Let's go over all elements and unwrap it with Awaited:

Promise reducer over arrays
Promise reducer over arrays

The only thing we need to do is to apply it to PromiseAll:

Solution, version 1
Solution, version 1

Let's see what happened in Playground. We still have failed tests. But why?

Fixing the issues with values

If we hover over constants we will see that the result is Promise<[]>, but we expected it to have elements' types inside a tuple.

This happens because as const converts an array to a tuple. For tuples T extends [infer H, ...infer Tail] ? true : false returns false because we forgot readonly keyword.

But instead of changing PromiseReducer let's have a look at promiseAllTest3:

Type inferred from promiseAllTest3
Type inferred from promiseAllTest3

Type T is inferred as (number | Promise<number>)[] instead of [number, number, Promise<number>]. There is an approach to have values as tuple instead of array in types:

Make the values a tuple
Make the values a tuple
  1. We added [...T] instead of T
  2. We say that [...T] is readonly to work with tuples only
  3. We added Generic Constrain to use spread in tuples

All together:

Solution
Solution

That's it 🔥

Solution is available on Playground

Have a wonderful evening 🌇

typescript

Comments

Alexey Berezin profile image

Written by Alexey Berezin who loves London 🏴󠁧󠁢󠁥󠁮󠁧󠁿, players ⏯ and TypeScript 🦺 Follow me on Twitter