Here is what I want to do:
Promise.all([aurelia.start(), entityManagerProvider.initialize()])
.then((results:Array) => {
let aureli
I have the same issue with you, but with this code, all work perfectly.
type TList = Promise<Aurelia> | Promise<void>;
const foo: TList[] = [aurelia.start(), entityManagerProvider.initialize()];
Promise.all<TList>(foo).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());
I somehow landed here when I was looking for return type of Promise.all()
since straightforward [Promise<any>, Promise<any>]
is obviously not working.
Eventually it turned out to be simplier than it seems:
const severalMongoDbOperations: Promise<[DeleteWriteOpResultObject, UpdateWriteOpResult]> =
() => Promise.all([
mongo.deleteOne({ ... }),
mongo.updateOne({ ... })
]);
Later it can be used with .then()
or:
try {
const ops: [DeleteWriteOpResultObject, UpdateWriteOpResult] = await severalMongoDbOperations();
} catch (e) {
// Process rejection
}
This is a weakness in the TypeScript and its Promise.all
signature. Its generally best to have arrays with consistent types. You can do the following manually though:
let foo : [Promise<Aurelia>,Promise<void>] = [aurelia.start(), entityManagerProvider.initialize()];
Promise.all(foo).then((results:any[]) => {
let aurelia: any = results[0];
aurelia.setRoot();
});
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'.
...
});