TypeScript,如何键入将 Promise[] <T>转换为 Promise<T[]> 的函数?



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

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);

没有类型错误并且CCD_ 1被正确地键入为CCD_;

但如果我这样做:

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<string>| Promise>number>([]"的参数不可分配给类型为"Promise&字符串>[]'。

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

我可以通过以下操作来解决此问题:

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

则CCD_ 5被正确地键入为CCD_

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

注意:我也尝试过重载类似于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>;
}

它们的关键是推断最初来自内部数组的并集类型。

游乐场

您的函数只是在做与Promise.all相同的事情,所以只需将其定义为别名,并将出色的键入推迟到原始函数的:

const allPromises = Promise.all;
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);

TypeScript游乐场链接

最新更新