TypeScript:Promise.all 不处理联合类型 [英] TypeScript: Promise.all doesn't handle union types

查看:93
本文介绍了TypeScript:Promise.all 不处理联合类型的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有以下一段代码导致 TypeScript 编译错误:

I have the following piece of code that results in compile error in TypeScript:

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

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

错误如下

没有与此调用匹配的过载.最后一次重载给出了以下错误.'(Promise | Promise)[]' 类型的参数不可分配给 'Iterable>' 类型的参数.'Symbol.iterator.next(...)' 返回的类型在这些类型之间不兼容.

No overload matches this call. The last overload gave the following error. Argument of type '(Promise | Promise)[]' is not assignable to parameter of type 'Iterable>'. The types returned by 'Symbol.iterator.next(...)' are incompatible between these types.

为了记录,删除联合类型按预期工作:

For the record, removing the union type works as intended:

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

You can see the error for yourself here https://www.typescriptlang.org/play/?ssl=4&ssc=3&pln=1&pc=1#code/C4TwDgpgBACgTgewLYEsDOBDARgG2gXigAoiBKKfAPlkVTQgB41g4UA7Ac0vIB9iyK1eMnSM2AVyRYIcbgG4AsACgAxgjbMoAM3FsVFKBjQg9xMLXTY8ALhojMuCOSpQA3sqiGA7hhTA7dBAAdBg4OEQA2ub2VhBkALqkikoAvnJAA

联合类型不能与 Promise.all 结合使用吗?

Is it not possible to use union types in combination with Promise.all?

我知道可以使用诸如 () => 之类的东西.Promise 代替.但是在一个异步函数很多、类型很大的高级应用中,把函数的联合转换成联合的函数并不容易.从代码的角度来看也不太实用.

I know it's possible to use something like () => Promise<string|number> instead. But in an advanced application with a lot of asynchronous functions and big types, it is not easy to convert union of functions into function of union. It's not very practical from the code perspective as well.

推荐答案

更新

这是其中一种情况,其中 类型推断当前 a> 失败.最简单的解决方案是手动添加泛型类型参数:

Update

This is one of the cases, where type inference with current promise type declarations fails. Simplest solution is to just add the generic type argument manually:

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

你可以推断 string |号码 自动:

type PromiseReturn<T> = T extends () => Promise<infer I> ? I : never
const res = await Promise.all<PromiseReturn<Promisable>>([promisable()]);

使用 TypeScript 4.1:更复杂、可能嵌套的 Promise可以使用 自定义递归Awaited 像这样输入:

With TypeScript 4.1: More complex, potentially nested Promise types can be resolved and flattened with a custom recursive Awaited type like this:

type Awaited<T> = T extends PromiseLike<infer U> ? Awaited<U> : T;

游乐场

更新:awaited 类型运算符是 推迟到更高版本 - 完全不清楚是否会发布.

Update: The awaited type operator is delayed to later versions - not clear whether it will be released at all.

这是一个已知问题.好消息:TS 3.9(即将推出测试版)将发布 改进的承诺类型:

This is a known issue. Good news: TS 3.9 (beta soon) will come out with improved promise types:

我想重新引入 #17077 中的 awaited 类型运算符 满足我们对一种机制的需求,为Promise.allPromise.racePromise.allSettled 等方法递归解包类似 Promise 的类型Promise.prototype.thenPromise.prototype.catch.

I would like to reintroduce the awaited type operator from #17077 to meet our needs for a mechanism to recursively unwrap a Promise-like type for methods like Promise.all, Promise.race, Promise.allSettled, Promise.prototype.then, and Promise.prototype.catch.

类型声明 Promise.all 和其他人使用新的 awaited 类型运算符.如果您与每晚构建, Promise.all 现在可以正确解析为 Promise<(string | number)[]>:

Type declarations of Promise.all and others use the new awaited type operator. If you test with the nightly build, Promise.all now correctly resolves to 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,可以手动分配泛型类型参数:

In contrast, TS 3.8 can't handle it. For versions < 3.9, you can manually assign the generic type argument:

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

这篇关于TypeScript:Promise.all 不处理联合类型的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆