A typed Promise.all for tuples
Write all(values), an analogue of Promise.all without using Promise.all itself. It waits for all values (promises or plain ones), returns the results in the same order, and rejects with the first error.
The main thing here is the type: for all([1, Promise.resolve("a")]) the result must be Promise<[number, string]>, a tuple, not (string | number)[]. Nested promises are unwrapped down to the value.
Ctrl+Enter runs the tests. Tab indents; to leave the editor with the keyboard, press Esc and then Tab. Your code is saved in this browser.
Tests (7)
Type tests are checked by the TypeScript compiler in strict mode. Expect<Equal<A, B>> passes when the types match exactly, and // @ts-expect-error passes when the next line does not compile. The first run downloads the compiler, so it takes a few seconds.
- types
const p = all([1, Promise.resolve('a'), Promise.resolve(true)]); type _ = Expect<Equal<typeof p, Promise<[number, string, boolean]>>>;
- types
const p = all([1, 'x'] as const); type _ = Expect<Equal<typeof p, Promise<[1, 'x']>>>;
- types
const p = all([] as unknown as [Promise<Promise<number>>, string]); type _ = Expect<Equal<typeof p, Promise<[number, string]>>>;
expect(await all([1, Promise.resolve(2), wait(20).then(() => 3)])).toEqual([1, 2, 3]);
const slow = wait(30).then(() => 'slow'); const fast = Promise.resolve('fast'); expect(await all([slow, fast])).toEqual(['slow', 'fast']);
await expect(all([Promise.resolve(1), Promise.reject(new Error('boom'))])).rejects.toThrow('boom');
expect(await all([])).toEqual([]);