"Promise.all is parallelism with tuples preserved."
What Promise.all does
Promise.all([p1, p2, p3]) takes an array (or tuple) of Promises and returns a Promise that resolves when all the input Promises resolve. The resolved value is an array of the resolved values, in the same order.
At the type level, when you pass a tuple, the result preserves the tuple shape: Promise.all([Promise.resolve(1), Promise.resolve('a')]) is Promise<[number, string]>. This means destructuring after await preserves each position's type — [a, b] gets a: number; b: string.
Sequential vs parallel
Two awaited calls in a row run sequentially. const a = await fa(); const b = await fb() takes time(fa) + time(fb). Promise.all runs in parallel: const [a, b] = await Promise.all([fa(), fb()]) takes max(time(fa), time(fb)).
For independent async calls, Promise.all is almost always the right move. The compiler can't tell whether your calls are independent — that's your job.
Failure behavior
Promise.all rejects fast: if any input Promise rejects, the whole thing rejects with that error. For 'wait for all, collect both successes and failures,' use Promise.allSettled (returns an array of { status: 'fulfilled' | 'rejected', value? / reason? }).