I want to create some generic handling for Promise.allSettled
Currently allSettled returns list of fulfilled and rejected results. I don't care and I really don't want to make handling everywhere of it. I want to use it same as Promise.all if any error, reject, BUT wait till all ends. It's important.
private async allAndWait<T>(values: Iterable<PromiseLike<T>>): Promise<T[]> {
const allSettled = await Promise.allSettled(values);
const rejected = allSettled.find((promise) => promise.status === 'rejected') as PromiseRejectedResult | undefined;
if (rejected) {
throw rejected.reason;
}
return allSettled.map((promise) => (promise as PromiseFulfilledResult<T>).value);
}
Created something like this but it does not allow me to send array of different type of promises. And return type is only of the first type, while I want to have exactly the same as with Promise.all experience

TLDR:
Here is my hopefully comprehensible process:
I don't know why but in your code
Tdoesn't get inferred correctly. I'd have expected that theTto be a union of all types that the input tuple has (sostring | number). We can do this by shifting the type deceleration to the generic. (just shiftingPromiseLike<unknown>would be enough).This admittedly doesn't help us much, as we need T to be a tuple and not a union. As you want the return types to be ordered (and not all of them being typeof the union of all input types). Whether we get such a tuple in the form of
[PromiseLike<string>, PromiseLike<number>]or[string, number]doesn't matter much, as we can pluck the types from the former with a mapped type. So assuming we have such a (PromiseLike) tupleTwe can simple do:My first intuition was to use a rest operator:
Note that we had to drop the
Iteratableover an array. As we cannot use the rest operator onIteratables. Note thatIteratables do not tuple like types. So we cannot say that the first element is typeof string and the second one typeof number, which we need here. We can later do a overload for this use case (in case you really need it) and provide a less powerful type implementation that works with unions. But first we need to fix that you cant even pass in arrays. You could do it like this:But this doesn't strictly follow your requested type implementation. Note that we cannot just omit the rest operator from the function decleration, as this would again convert the tuple to a union type. So we have to apply a trick:
We require two things here via a intersection type: first,
valuesmust be typeof Iterable<Promise>. And second, we infer a very generic tupleT, so that we can use it later for the export. This line is heavily inspired by thePromise.alltype declaration and I don't know why here:T extends readonly unknown[] | []the union with[]is necessary, but it is.This only leaves the less powerful overload for
Iteratables:Which we have to put below the other overload, as it is more generic and would conform to all possible inputs (so the other overload would never be reached).