假设我有一些函数,比如:

function allPromises<T>(array: Promise<T>[]): Promise<T[]> {
  return Promise.all(array);
}

(注:这是有意设计为最低限度的复制)

如果我这么做了,效果很好:

const p1: Promise<string> = new Promise((resolve) => resolve('1'));
const p2: Promise<string> = new Promise((resolve) => resolve('2'));
const test1 = [p1, p2];
const res1 = allPromises(test1);

没有输入错误,res1正确输入为Promise<string[]>

但如果我这么做了:

const p1: Promise<string> = new Promise((resolve) => resolve('1'));
const p2: Promise<number> = new Promise((resolve) => resolve(2));
const test2 = [p1, p2];
const res2 = allPromises(test2);

现在我接到TS投诉:

类型为"(Promise&lt;string&gt;|Promise&lt;number&gt;)的参数[]不可分配给"Promise"类型的参数&lt;字符串&gt;[]'.

这似乎是因为test2被输入为(Promise<number> | Promise<string>)[]

我可以通过以下方式解决这个问题:

const test2: Promise<string | number>[] = [p1, p2];

然后res2正确地被输入为Promise<(string | number)[]>

但是,有没有一种方法可以键入我的函数,这样它就可以正确地推断出类型,而不是强迫我以这种方式显式地声明数组的类型?

注意:我也try 过重载函数,类似于Promise.all键入的方式,但它也失败了,需要我显式键入数组,以便TS接受它:

function allPromises<T1, T2>(array: [Promise<T1>, Promise<T2>]): Promise<[T1, T2]>
function allPromises<T>(array: Promise<T>[]): Promise<T[]>
function allPromises(array: Promise<unknown>[]): Promise<unknown[]> {
  return Promise.all(array);
}

这种超负荷也没有帮助:

function allPromises<T1, T2>(array: (Promise<T1> | Promise<T2>)[]): Promise<(T1 | T2)[]>

我希望在TS V3中实现这一点...我在V4中看到了一些新类型.5+对这一点很有用,但我暂时还停留在V3中.

推荐答案

我让它和

type UnwrapPromiseArr<T> = T extends Promise<infer R>[]
  ? Promise<R[]>
  : never;

function allPromises<T extends Promise<unknown>[]>(array: T): UnwrapPromiseArr<T> {
  return Promise.all(array) as UnwrapPromiseArr<T>;
}

它们的关键是推断最初来自内部数组的联合类型.

Playground

Typescript相关问答推荐

定义JMX的类型:类型上不存在属性键

使用前的组件渲染状态更新

在这种情况下,如何获得类型安全函数的返回值?

如何在函数参数中使用(或模仿)`success`的行为?

`((PrevState:NULL)=>;NULL)|null`是什么意思?

typescribe警告,explate—deps,useEffect依赖项列表

Next.js错误:不变:页面未生成

编剧错误:正在等待Expect(Locator).toBeVisible()

从TypeScrip中的其他类型检索泛型类型

ANGLE独立组件布线错误:没有ActivatedRouting提供程序

类型TTextKey不能用于索引类型 ;TOption

Vue3 Uncaught SyntaxError:每当我重新加载页面时,浏览器控制台中会出现无效或意外的令牌

使用TypeScrip5强制使用方法参数类型的实验方法修饰符

TaskListProps[]类型不可分配给TaskListProps类型

编剧- Select 动态下拉选项

有没有办法在Reaction组件中动态导入打字脚本`type`?

递归类型别名的Typescript 使用

如何以类型安全的方式指定键的常量列表,并从该列表派生所挑选的接口?

如何正确键入泛型相对记录值类型?

在类型{}上找不到带有string类型参数的索引签名 - TypeScript