Как использовать Promise.all() с Typescript
Вот что я хочу сделать:
Promise.all([aurelia.start(), entityManagerProvider.initialize()])
.then((results:Array<any>) => {
let aurelia: any = results[0];
aurelia.setRoot();
});
aurelia.start()
возвращает тип Aurelia, а initialize()
возвращает void.
Компилятор выдает сообщение об ошибке, что тип не может быть выведен из использования.
Я пытаюсь добиться того, чтобы они запускались одновременно, так как они оба являются очень длинными процессами, а затем запускаются Aurelia.setRoot();
Ответы
Ответ 1
Это слабость в TypeScript и ее подписи Promise.all
. В целом лучше всего иметь массивы с согласованными типами. Вы можете сделать следующее вручную:
let foo : [Promise<Aurelia>,Promise<void>] = [aurelia.start(), entityManagerProvider.initialize()];
Promise.all(foo).then((results:any[]) => {
let aurelia: any = results[0];
aurelia.setRoot();
});
Ответ 2
Поскольку Promise::all
является универсальной функцией, вы можете объявить типы возврата каждого обещания следующим образом:
Promise.all<Aurelia, void>([
aurelia.start(),
entityManagerProvider.initialize()
])
.then(([aurelia]) => aurelia.setRoot());
Ответ 3
Если вы хотите сохранить безопасность типов, можно расширить собственное определение типа объекта Promise
(типа PromiseConstructor
) с дополнительными сигнатурами перегрузки для вызова Promise.all
с конечным числом необязательно взаимно назначаемых значений:
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]>;
...
}
Добавьте столько перегрузок, сколько вам нужно. Этот подход обеспечивает полную безопасность типов для всех элементов в аргументе value
обратного вызова onfulfilled
:
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'.
...
});
Ответ 4
По крайней мере, начиная с TypeScript 2.7.1
и далее, кажется, что компилятор разрешает типы без посторонней помощи, используя следующий синтаксис:
Promise.all([fooPromise, barPromise]).then(([foo, bar]) => {
// compiler correctly warns if someField not found from foo type
console.log(foo.someField);
});
Шляпа: @JamieBirch (из комментария к ответу @AndrewKirkegaard)