-
Notifications
You must be signed in to change notification settings - Fork 12.7k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
4.0: Cannot use variadic tuples in Promise.all #39788
Comments
I'm guessing the type definitions for Promise.all haven't been updated to take advantage of variadic tuples. I'm not sure of the process here, can I submit a PR to update them targeting the 4.0 branch? Here's some code using a new definition for Promise.all where it works almost as expected: declare const foo: Promise<string>;
declare const bar: Promise<number>[];
declare interface PromiseConstructor {
all<T extends readonly unknown[]>(values: readonly [...T]): Promise<[...T]>
}
async function m() {
const p = await Promise.all([
foo,
...bar
])
} For some reason EDIT: Followup, I got it working!declare const foo: Promise<string>;
declare const bar: Promise<number>[];
declare interface PromiseConstructor {
all<T extends readonly unknown[]>(values: [...T]): { [P in keyof T]: T[P] extends Promise<infer U> ? U : never }
}
async function m() {
const p = await Promise.all([
foo,
...bar
])
} |
Here's a working definition: type Awaited<T> = T extends PromiseLike<infer U> ? U : T;
declare function all<T extends unknown[]>(values: readonly [...T]): Promise<{ [P in keyof T]: Awaited<T[P]> }>; We have yet to update the let p = Promise.all<string, number>([p1, p2]); With the variadic tuple definition that would have to be written let p = Promise.all<[string, number]>([p1, p2]); @rbuckton Anything to add? |
Ha, you must have commented just as I figured out the definition on my own - good timing! Would be a shame to not be able to make this change as it seems like a perfect use case for variadic tuples in the standard library. I wonder if the variadic tuple form could be added as another overload? |
I've had concerns about The issue we run into is that if we move the variadic tuple version first in the overload list (so that we use it when performing inference for the type arguments), then we run into issues with existing
I'm not sure we can properly fix one without breaking the other, unless we can modify the inference and overload resolution algorithms in a non-breaking way. |
@rbuckton Regarding type Awaited<T> = T extends PromiseLike<infer U> ? Awaited4<U> : T;
type Awaited4<T> = T extends PromiseLike<infer U> ? Awaited3<U> : T;
type Awaited3<T> = T extends PromiseLike<infer U> ? Awaited2<U> : T;
type Awaited2<T> = T extends PromiseLike<infer U> ? Awaited1<U> : T;
type Awaited1<T> = T extends PromiseLike<infer U> ? U : T; It's not exactly clear to me what would break by putting an overload with the definition above (which is different from the one you had in your PR) first in the list. I think it would just permit |
There were a number of things |
It's worth pointing out that the declarations in @ahejlsberg's comment have the generic params inferred as type Awaited<T> = T extends PromiseLike<infer U> ? U : T;
declare function all<T extends unknown[]>(values: readonly [...T]): Promise<{ [P in keyof T]: Awaited<T[P]> }>;
declare const p1: Promise<number>[];
declare const p2: Promise<string>;
all([p2, ...p1]) // function all<[Promise<string>, ...Promise<number>[]]> |
@rbuckton what is the downside of doing a type Promise<A> =
A extends globalThis.Promise<any>
? A
: globalThis.Promise<A>
type test = Promise<Promise<Promise<"typescript">>> // Promise<"typescript"> |
Hello, i have one question
can we somehow do that? example wait(Promise.resolve(0), Promise.resolve('test')) => result type = [number, string] because for now i got this
The PromiseResultMap in vscode intellisense resolves as an array but the actual type is an Object with keys the indexes of the array, but i can not do something like |
@spideythewebhead, something like this? function all<T extends any[]>(...values: { [K in keyof T]: PromiseLike<T[K]> }) {
return Promise.all(values) as Promise<T>;
} |
FYI variadic tuple support within |
This works now! |
TypeScript Version: 4.0.0-beta
Search Terms:
variadic tuples promise.all
Code
Expected behavior:
p
should have type[string, ...number]
Actual behavior:
Type error
Playground Link: https://www.typescriptlang.org/play/?ts=4.0.0-dev.20200728&ssl=9&ssc=2&pln=1&pc=1#code/CYUwxgNghgTiAEYD2A7AzgF3gMyUgXPAAoxIC2AlmiADyYwUoDmAfANwCwAUKJLAsnRYARrEIlyVWigCuZYSBgsA2gF1OXblDQBPFGBwz9GCqnhkAFAEp4Ab27xHiVJngAHeAF54UAO5QKLAlKagA6KAgIC2UHJzjcJAAaWLjHUPTRGBT4VStuAF8gA
Related Issues: none
The text was updated successfully, but these errors were encountered: