How to use Promise.all() with Typescript
At least from TypeScript 2.7.1
onwards, the compiler seems to resolve the types without help, with a syntax like this:
Promise.all([fooPromise, barPromise]).then(([foo, bar]) => {
// compiler correctly warns if someField not found from foo's type
console.log(foo.someField);
});
Hat tip: @JamieBirch (from comment to @AndrewKirkegaard's answer)
If you'd like to keep type-safety, it's possible to extend the native type-definition of the Promise
object (of type PromiseConstructor
) with additional overload signatures for when Promise.all
is called with a finite number of not-necessarily inter-assignable values:
interface PromiseConstructor
{
all<T1, T2>(values: [T1 | PromiseLike<T1>, T2 | PromiseLike<T2>]): Promise<[T1, T2]>;
all<T1, T2, T3>(values: [T1 | PromiseLike<T1>, T2 | PromiseLike<T2>, T3 | PromiseLike<T3>]): Promise<[T1, T2, T3]>;
...
}
Add as many overloads as you need. This approach provides full type-safety for all elements in the value
argument of the onfulfilled
callback:
Promise.all([1, "string", true]).then(value =>
{
let a: number = value[0]; // OK
let b: number = value[1]; // Type 'string' is not assignable to type 'number'.
...
});
Its generally best to have arrays with consistent types. You can do the following manually though (passing in generic arguments):
Promise.all<Aurelia, void>(
[aurelia.start(), entityManagerProvider.initialize()
])
.then(results => {
let aurelia = results[0];
aurelia.setRoot();
});
Since Promise::all
is a generic function, you can declare the return types of each promise like this:
Promise.all<Aurelia, void>([
aurelia.start(),
entityManagerProvider.initialize()
])
.then(([aurelia]) => aurelia.setRoot());