Skip to content

Commit ea521d4

Browse files
authored
Adds 'Awaited' type alias and updates to Promise.all/race/allSettled/any (#45350)
* Adds 'Awaited' type alias and updates to Promise.all/race/allSettled/any * Use Awaited<T> with 'await' * Clean up overloads * Further restrict 'Awaited<T>' auto-wrapping for 'await'
1 parent cdd9314 commit ea521d4

38 files changed

+2142
-290
lines changed

src/compiler/checker.ts

Lines changed: 184 additions & 71 deletions
Large diffs are not rendered by default.

src/harness/fourslashInterfaceImpl.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1095,6 +1095,7 @@ namespace FourSlashInterface {
10951095
typeEntry("PromiseConstructorLike"),
10961096
interfaceEntry("PromiseLike"),
10971097
interfaceEntry("Promise"),
1098+
typeEntry("Awaited"),
10981099
interfaceEntry("ArrayLike"),
10991100
typeEntry("Partial"),
11001101
typeEntry("Required"),

src/lib/es2015.iterable.d.ts

Lines changed: 2 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -203,23 +203,15 @@ interface PromiseConstructor {
203203
* @param values An iterable of Promises.
204204
* @returns A new Promise.
205205
*/
206-
all<T>(values: Iterable<T | PromiseLike<T>>): Promise<T[]>;
206+
all<T>(values: Iterable<T | PromiseLike<T>>): Promise<Awaited<T>[]>;
207207

208208
/**
209209
* Creates a Promise that is resolved or rejected when any of the provided Promises are resolved
210210
* or rejected.
211211
* @param values An iterable of Promises.
212212
* @returns A new Promise.
213213
*/
214-
race<T>(values: Iterable<T>): Promise<T extends PromiseLike<infer U> ? U : T>;
215-
216-
/**
217-
* Creates a Promise that is resolved or rejected when any of the provided Promises are resolved
218-
* or rejected.
219-
* @param values An iterable of Promises.
220-
* @returns A new Promise.
221-
*/
222-
race<T>(values: Iterable<T | PromiseLike<T>>): Promise<T>;
214+
race<T>(values: Iterable<T | PromiseLike<T>>): Promise<Awaited<T>>;
223215
}
224216

225217
interface String {

src/lib/es2015.promise.d.ts

Lines changed: 2 additions & 74 deletions
Original file line numberDiff line numberDiff line change
@@ -18,79 +18,7 @@ interface PromiseConstructor {
1818
* @param values An array of Promises.
1919
* @returns A new Promise.
2020
*/
21-
all<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10>(values: readonly [T1 | PromiseLike<T1>, T2 | PromiseLike<T2>, T3 | PromiseLike<T3>, T4 | PromiseLike<T4>, T5 | PromiseLike<T5>, T6 | PromiseLike<T6>, T7 | PromiseLike<T7>, T8 | PromiseLike<T8>, T9 | PromiseLike<T9>, T10 | PromiseLike<T10>]): Promise<[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10]>;
22-
23-
/**
24-
* Creates a Promise that is resolved with an array of results when all of the provided Promises
25-
* resolve, or rejected when any Promise is rejected.
26-
* @param values An array of Promises.
27-
* @returns A new Promise.
28-
*/
29-
all<T1, T2, T3, T4, T5, T6, T7, T8, T9>(values: readonly [T1 | PromiseLike<T1>, T2 | PromiseLike<T2>, T3 | PromiseLike<T3>, T4 | PromiseLike<T4>, T5 | PromiseLike<T5>, T6 | PromiseLike<T6>, T7 | PromiseLike<T7>, T8 | PromiseLike<T8>, T9 | PromiseLike<T9>]): Promise<[T1, T2, T3, T4, T5, T6, T7, T8, T9]>;
30-
31-
/**
32-
* Creates a Promise that is resolved with an array of results when all of the provided Promises
33-
* resolve, or rejected when any Promise is rejected.
34-
* @param values An array of Promises.
35-
* @returns A new Promise.
36-
*/
37-
all<T1, T2, T3, T4, T5, T6, T7, T8>(values: readonly [T1 | PromiseLike<T1>, T2 | PromiseLike<T2>, T3 | PromiseLike<T3>, T4 | PromiseLike<T4>, T5 | PromiseLike<T5>, T6 | PromiseLike<T6>, T7 | PromiseLike<T7>, T8 | PromiseLike<T8>]): Promise<[T1, T2, T3, T4, T5, T6, T7, T8]>;
38-
39-
/**
40-
* Creates a Promise that is resolved with an array of results when all of the provided Promises
41-
* resolve, or rejected when any Promise is rejected.
42-
* @param values An array of Promises.
43-
* @returns A new Promise.
44-
*/
45-
all<T1, T2, T3, T4, T5, T6, T7>(values: readonly [T1 | PromiseLike<T1>, T2 | PromiseLike<T2>, T3 | PromiseLike<T3>, T4 | PromiseLike<T4>, T5 | PromiseLike<T5>, T6 | PromiseLike<T6>, T7 | PromiseLike<T7>]): Promise<[T1, T2, T3, T4, T5, T6, T7]>;
46-
47-
/**
48-
* Creates a Promise that is resolved with an array of results when all of the provided Promises
49-
* resolve, or rejected when any Promise is rejected.
50-
* @param values An array of Promises.
51-
* @returns A new Promise.
52-
*/
53-
all<T1, T2, T3, T4, T5, T6>(values: readonly [T1 | PromiseLike<T1>, T2 | PromiseLike<T2>, T3 | PromiseLike<T3>, T4 | PromiseLike<T4>, T5 | PromiseLike<T5>, T6 | PromiseLike<T6>]): Promise<[T1, T2, T3, T4, T5, T6]>;
54-
55-
/**
56-
* Creates a Promise that is resolved with an array of results when all of the provided Promises
57-
* resolve, or rejected when any Promise is rejected.
58-
* @param values An array of Promises.
59-
* @returns A new Promise.
60-
*/
61-
all<T1, T2, T3, T4, T5>(values: readonly [T1 | PromiseLike<T1>, T2 | PromiseLike<T2>, T3 | PromiseLike<T3>, T4 | PromiseLike<T4>, T5 | PromiseLike<T5>]): Promise<[T1, T2, T3, T4, T5]>;
62-
63-
/**
64-
* Creates a Promise that is resolved with an array of results when all of the provided Promises
65-
* resolve, or rejected when any Promise is rejected.
66-
* @param values An array of Promises.
67-
* @returns A new Promise.
68-
*/
69-
all<T1, T2, T3, T4>(values: readonly [T1 | PromiseLike<T1>, T2 | PromiseLike<T2>, T3 | PromiseLike<T3>, T4 | PromiseLike<T4>]): Promise<[T1, T2, T3, T4]>;
70-
71-
/**
72-
* Creates a Promise that is resolved with an array of results when all of the provided Promises
73-
* resolve, or rejected when any Promise is rejected.
74-
* @param values An array of Promises.
75-
* @returns A new Promise.
76-
*/
77-
all<T1, T2, T3>(values: readonly [T1 | PromiseLike<T1>, T2 | PromiseLike<T2>, T3 | PromiseLike<T3>]): Promise<[T1, T2, T3]>;
78-
79-
/**
80-
* Creates a Promise that is resolved with an array of results when all of the provided Promises
81-
* resolve, or rejected when any Promise is rejected.
82-
* @param values An array of Promises.
83-
* @returns A new Promise.
84-
*/
85-
all<T1, T2>(values: readonly [T1 | PromiseLike<T1>, T2 | PromiseLike<T2>]): Promise<[T1, T2]>;
86-
87-
/**
88-
* Creates a Promise that is resolved with an array of results when all of the provided Promises
89-
* resolve, or rejected when any Promise is rejected.
90-
* @param values An array of Promises.
91-
* @returns A new Promise.
92-
*/
93-
all<T>(values: readonly (T | PromiseLike<T>)[]): Promise<T[]>;
21+
all<T extends readonly unknown[] | []>(values: T): Promise<{ -readonly [P in keyof T]: Awaited<T[P]> }>;
9422

9523
// see: lib.es2015.iterable.d.ts
9624
// all<T>(values: Iterable<T | PromiseLike<T>>): Promise<T[]>;
@@ -101,7 +29,7 @@ interface PromiseConstructor {
10129
* @param values An array of Promises.
10230
* @returns A new Promise.
10331
*/
104-
race<T>(values: readonly T[]): Promise<T extends PromiseLike<infer U> ? U : T>;
32+
race<T extends readonly unknown[] | []>(values: T): Promise<Awaited<T[number]>>;
10533

10634
// see: lib.es2015.iterable.d.ts
10735
// race<T>(values: Iterable<T>): Promise<T extends PromiseLike<infer U> ? U : T>;

src/lib/es2020.promise.d.ts

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -17,14 +17,13 @@ interface PromiseConstructor {
1717
* @param values An array of Promises.
1818
* @returns A new Promise.
1919
*/
20-
allSettled<T extends readonly unknown[] | readonly [unknown]>(values: T):
21-
Promise<{ -readonly [P in keyof T]: PromiseSettledResult<T[P] extends PromiseLike<infer U> ? U : T[P]> }>;
20+
allSettled<T extends readonly unknown[] | []>(values: T): Promise<{ -readonly [P in keyof T]: PromiseSettledResult<Awaited<T[P]>> }>;
2221

2322
/**
2423
* Creates a Promise that is resolved with an array of results when all
2524
* of the provided Promises resolve or reject.
2625
* @param values An array of Promises.
2726
* @returns A new Promise.
2827
*/
29-
allSettled<T>(values: Iterable<T>): Promise<PromiseSettledResult<T extends PromiseLike<infer U> ? U : T>[]>;
28+
allSettled<T>(values: Iterable<T | PromiseLike<T>>): Promise<PromiseSettledResult<Awaited<T>>[]>;
3029
}

src/lib/es2021.promise.d.ts

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,5 +19,12 @@ interface PromiseConstructor {
1919
* @param values An array or iterable of Promises.
2020
* @returns A new Promise.
2121
*/
22-
any<T>(values: (T | PromiseLike<T>)[] | Iterable<T | PromiseLike<T>>): Promise<T>
22+
any<T extends readonly unknown[] | []>(values: T): Promise<Awaited<T[number]>>;
23+
24+
/**
25+
* The any function returns a promise that is fulfilled by the first given promise to be fulfilled, or rejected with an AggregateError containing an array of rejection reasons if all of the given promises are rejected. It resolves all elements of the passed iterable to promises as it runs this algorithm.
26+
* @param values An array or iterable of Promises.
27+
* @returns A new Promise.
28+
*/
29+
any<T>(values: Iterable<T | PromiseLike<T>>): Promise<Awaited<T>>
2330
}

src/lib/es5.d.ts

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1472,6 +1472,19 @@ interface Promise<T> {
14721472
catch<TResult = never>(onrejected?: ((reason: any) => TResult | PromiseLike<TResult>) | undefined | null): Promise<T | TResult>;
14731473
}
14741474

1475+
/**
1476+
* Recursively unwraps the "awaited type" of a type. Non-promise "thenables" should resolve to `never`. This emulates the behavior of `await`.
1477+
*/
1478+
type Awaited<T> =
1479+
T extends null | undefined ? T : // special case for `null | undefined` when not in `--strictNullChecks` mode
1480+
T extends object ? // `await` only unwraps object types with a callable then. Non-object types are not unwrapped.
1481+
T extends { then(onfulfilled: infer F): any } ? // thenable, extracts the first argument to `then()`
1482+
F extends ((value: infer V) => any) ? // if the argument to `then` is callable, extracts the argument
1483+
Awaited<V> : // recursively unwrap the value
1484+
never : // the argument to `then` was not callable.
1485+
T : // argument was not an object
1486+
T; // non-thenable
1487+
14751488
interface ArrayLike<T> {
14761489
readonly length: number;
14771490
readonly [n: number]: T;

tests/baselines/reference/asyncArrowFunction9_es2017.errors.txt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ tests/cases/conformance/async/es2017/asyncArrowFunction/asyncArrowFunction9_es20
1616
!!! error TS1005: ',' expected.
1717
~~~~~~~
1818
!!! error TS2403: Subsequent variable declarations must have the same type. Variable 'Promise' must be of type 'PromiseConstructor', but here has type 'any'.
19-
!!! related TS6203 /.ts/lib.es2015.promise.d.ts:150:13: 'Promise' was also declared here.
19+
!!! related TS6203 /.ts/lib.es2015.promise.d.ts:78:13: 'Promise' was also declared here.
2020
~
2121
!!! error TS1005: ',' expected.
2222
~~

tests/baselines/reference/asyncArrowFunction9_es5.errors.txt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ tests/cases/conformance/async/es5/asyncArrowFunction/asyncArrowFunction9_es5.ts(
1616
!!! error TS1005: ',' expected.
1717
~~~~~~~
1818
!!! error TS2403: Subsequent variable declarations must have the same type. Variable 'Promise' must be of type 'PromiseConstructor', but here has type 'any'.
19-
!!! related TS6203 /.ts/lib.es2015.promise.d.ts:150:13: 'Promise' was also declared here.
19+
!!! related TS6203 /.ts/lib.es2015.promise.d.ts:78:13: 'Promise' was also declared here.
2020
~
2121
!!! error TS1005: ',' expected.
2222
~~

tests/baselines/reference/asyncArrowFunction9_es6.errors.txt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ tests/cases/conformance/async/es6/asyncArrowFunction/asyncArrowFunction9_es6.ts(
1616
!!! error TS1005: ',' expected.
1717
~~~~~~~
1818
!!! error TS2403: Subsequent variable declarations must have the same type. Variable 'Promise' must be of type 'PromiseConstructor', but here has type 'any'.
19-
!!! related TS6203 /.ts/lib.es2015.promise.d.ts:150:13: 'Promise' was also declared here.
19+
!!! related TS6203 /.ts/lib.es2015.promise.d.ts:78:13: 'Promise' was also declared here.
2020
~
2121
!!! error TS1005: ',' expected.
2222
~~

0 commit comments

Comments
 (0)