TypeScript: Promise.all не обрабатывает типы объединения - PullRequest
6 голосов
/ 19 марта 2020

У меня есть следующий фрагмент кода, который приводит к ошибке компиляции в TypeScript:

type Promisable = (() => Promise<string>) | (() => Promise<number>);

const func = async (promisable: Promisable) => {
  await Promise.all([promisable()]);
};

Ошибка выглядит следующим образом

Никакая перегрузка не соответствует этому вызову. Последняя перегрузка дала следующую ошибку. Аргумент типа '(Promise | Promise) []' нельзя назначить параметру типа 'Iterable>'. Типы, возвращаемые функцией Symbol.iterator.next (...), несовместимы между этими типами.

Для записи удаление типа объединения работает так, как задумано:

type Promisable = () => Promise<string>;

const func = async (promisable: Promisable) => {
  await Promise.all([promisable()]);
};

Вы можете увидеть ошибку для себя здесь https://www.typescriptlang.org/play/?ssl=4&ssc=3&pln=1&pc=1#code / C4TwDgpgBACgTgewLYEsDOBDARgG2gXigAoiBKKfAPlkVTQgB41g4UA7Ac0vIB9iyK1eMnSM2AVyRYIcbgG4AsACgAxgjbMoAM3FsVFKBjQg9xMLXTY8ALhojMuCOSpQA3sqiGA7hhTA7dBAAdBg4OEQA2ub2VhBkALqkikoAvnJAA

1017 * это не представляется возможным использовать типы профсоюзов в сочетании с Promise.all

EDIT: Я знаю, что вместо этого можно использовать что-то вроде () => Promise<string|number>. Но в сложном приложении с большим количеством асинхронных функций и больших типов непросто преобразовать объединение функций в функцию объединения. Это не очень практично с точки зрения кода.

Ответы [ 2 ]

5 голосов
/ 24 марта 2020

Обновление: awaited оператор типа отложен до более поздней версии .


Это известная проблема . Хорошие новости: TS 3.9 (скоро выйдет бета) выйдет с улучшенными типами обещаний :

Я хотел бы снова ввести оператор типа awaited из # 17077 для удовлетворения наших потребностей в механизме рекурсивного развертывания типа Promise для таких методов, как Promise.all, Promise.race, Promise.allSettled, Promise.prototype.then и Promise.prototype.catch.

Объявления типов из Promise.all и другие используют новый оператор типа awaited. Если вы тестировали с ночной сборкой , Promise.all теперь правильно разрешается в Promise<(string | number)[]>:

type Promisable = (() => Promise<string>) | (() => Promise<number>);

declare const promisable: Promisable
const res = await Promise.all([promisable()]); // res: (string | number)[]

В отличие от этого, TS 3.8 не может справиться с этим, Для версий <3.9 вы можете <a href="https://www.typescriptlang.org/play/?ts=3.8.3&ssl=6&ssc=92&pln=5&pc=1#code/KYDwDg9gTgLgBAbzgXwLACgMwJ5mHABSggFsBLAZwEMAjAG3wF44AKFgSjkYD5DjyKwADwUYUMgDsA5t04AfVhy68ipSsIkBXEjWBRZAbgwYAJsADGdKlHzmIE0XDD9KtBgC4%20a6vWAY7DvA2FFxwVADuVGTwqgLAAHRUdHQiYpJScApaOnrcLADazt5uwBwAuuwGcAD01XDBniyi4tKZcNm6UOz5ZUA" rel="nofollow noreferrer"> вручную назначить аргумент типа generi c:

declare const promisable: Promisable
const res = await Promise.all<string | number>([promisable()]); // res: (string | number)[]
0 голосов
/ 19 марта 2020

Вам не нужен такой подробный тип, это подойдет:

type Promisable = (() => Promise<string|number>);
const func = async (promisable: Promisable) => {
  await Promise.all([promisable()]);
};
...