Подтвердить что ты не робот

Как использовать 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();

4b9b3361

Ответ 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)