TypeScript Promise.all and Promise.allSettled infer incorrect types from Array subclasses

q5lcpyga  于 6个月前  发布在  TypeScript
关注(0)|答案(4)|浏览(57)

lib 更新请求

配置检查

我的编译目标是 ES2020 ,我的库是 the default

缺失/不正确的定义

Promise.all
Promise.allSettled

示例代码

declare class ArrayChild<T> extends Array<T> {}

declare const array: Array<Promise<number>>
declare const child: ArrayChild<Promise<number>>

Promise.all(array).then(a => a /* number[] */) 
Promise.allSettled(array).then(a => a /* PromiseSettledResult<number>[] */)

Promise.all(child).then(a => a /* {[K in keyof ArrayChild]: number} */) 
Promise.allSettled(child).then(a => /* {[K in keyof ArrayChild]: PromiseSettledResult<number>} */)

Playground链接

文档链接

Promise.all
Promise.allSettled

可能的修复方法

推断出的值应该是 number[] 类型,就像 Array 类中发生的情况一样。在链接的 playground 中,可以看到 Promise.allPromise.allSettled 用一个 Iterable 类型的对象推断出正确的类型。这种不期望的行为只发生在 Array 子类中。我快速尝试将原始签名从:

allSettled<T extends readonly unknown[] | []>(values: T): Promise<{ -readonly [P in keyof T]: PromiseSettledResult<Awaited<T[P]>> }>;
all<T extends readonly unknown[] | []>(values: T): Promise<{ -readonly [P in keyof T]: Awaited<T[P]> }>;

更改为:

allSettled<T extends Promise<unknown>[]>(values: T): Promise<T extends Promise<infer S>[] ? PromiseSettledResult<S>[] : never>
all<T extends Promise<unknown>[]>(values: T): Promise<T extends Promise<infer S>[] ? S[] : never>

它按预期工作:Playground链接

pexxcrt2

pexxcrt21#

这将破坏元组,而我认为在promise方法中,元组的使用案例比数组子类更常见。

示例

jucafojl

jucafojl2#

是的,我们肯定不能在这里破坏元组推断。似乎还有另一种写法,但我们必须权衡复杂性和性能成本与它在实际代码中平均的实用性。

7lrncoxx

7lrncoxx3#

扩展数组类,尽管这在语言中并不常见,但这个bug可能会成为库开发的障碍。例如,一旦有机会,我将花一些时间寻找解决方案!

chy5wohz

chy5wohz4#

虽然我没有完全测试这个,但看起来它正在工作。

declare function all<T extends [unknown] | ArrayLike<unknown> | Iterable<unknown>>(values: T): Promise<
    T extends {[P in 0]: unknown} ? 
        {-readonly [P in keyof T]: Awaited<T[P]>} : 
            T extends ArrayLike<infer S> | Iterable<infer S> ? Awaited<S>[] : never 
>

Playground链接

相关问题