Skip to content

Commit 064cbf3

Browse files
committed
feat: add Promise.allKeyed and Promise.allSettledKeyed to esnext
1 parent 9a8581c commit 064cbf3

20 files changed

Lines changed: 706 additions & 11 deletions

‎tsc/internal/bundled/embed_generated.go‎

Lines changed: 4 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

‎tsc/internal/bundled/libs/lib.esnext.d.ts‎

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,3 +25,4 @@ and limitations under the License.
2525
/// <reference lib="esnext.typedarrays" />
2626
/// <reference lib="esnext.temporal" />
2727
/// <reference lib="esnext.date" />
28+
/// <reference lib="esnext.promise" />
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
/*! *****************************************************************************
2+
Copyright (c) Microsoft Corporation. All rights reserved.
3+
Licensed under the Apache License, Version 2.0 (the "License"); you may not use
4+
this file except in compliance with the License. You may obtain a copy of the
5+
License at http://www.apache.org/licenses/LICENSE-2.0
6+
7+
THIS CODE IS PROVIDED ON AN *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
8+
KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY IMPLIED
9+
WARRANTIES OR CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE,
10+
MERCHANTABILITY OR NON-INFRINGEMENT.
11+
12+
See the Apache Version 2.0 License for specific language governing permissions
13+
and limitations under the License.
14+
***************************************************************************** */
15+
16+
17+
/// <reference lib="es2020.promise" />
18+
/// <reference lib="es2025.promise" />
19+
20+
interface PromiseConstructor {
21+
/**
22+
* Creates a Promise that is resolved with an object of results when all of the provided Promises resolve,
23+
* or rejected when any Promise is rejected.
24+
* @param promises An object of Promises.
25+
* @returns A new Promise.
26+
*/
27+
allKeyed<T extends object>(promises: T): Promise<{ -readonly [P in keyof T]: Awaited<T[P]>; }>;
28+
29+
/**
30+
* Creates a Promise that is resolved with an object of results when all of the provided Promises resolve or reject.
31+
* @param promises An object of Promises.
32+
* @returns A new Promise.
33+
*/
34+
allSettledKeyed<T extends object>(promises: T): Promise<{ -readonly [P in keyof T]: PromiseSettledResult<Awaited<T[P]>>; }>;
35+
}

‎tsc/internal/bundled/libs_generated.go‎

Lines changed: 1 addition & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

‎tsc/internal/compiler/program_test.go‎

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -111,6 +111,7 @@ var esnextLibs = []string{
111111
"lib.es2025.iterator.d.ts",
112112
"lib.es2025.promise.d.ts",
113113
"lib.es2025.regexp.d.ts",
114+
"lib.esnext.promise.d.ts",
114115
"lib.esnext.array.d.ts",
115116
"lib.esnext.collection.d.ts",
116117
"lib.esnext.date.d.ts",

‎tsc/internal/tsoptions/enummaps.go‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -107,8 +107,8 @@ var LibMap = collections.NewOrderedMapFromList([]collections.MapEntry[string, an
107107
{Key: "esnext.string", Value: "lib.es2024.string.d.ts"},
108108
{Key: "esnext.float16", Value: "lib.es2025.float16.d.ts"},
109109
{Key: "esnext.iterator", Value: "lib.es2025.iterator.d.ts"},
110-
{Key: "esnext.promise", Value: "lib.es2025.promise.d.ts"},
111110
// ESNext By-feature options
111+
{Key: "esnext.promise", Value: "lib.esnext.promise.d.ts"},
112112
{Key: "esnext.array", Value: "lib.esnext.array.d.ts"},
113113
{Key: "esnext.collection", Value: "lib.esnext.collection.d.ts"},
114114
{Key: "esnext.date", Value: "lib.esnext.date.d.ts"},

‎tsc/testdata/baselines/reference/compiler/libReplacement(libreplacement=true).trace.json‎

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1090,6 +1090,19 @@ Searching all ancestor node_modules directories for fallback extensions: JavaScr
10901090
Directory '/.src/node_modules' does not exist, skipping all lookups in it.
10911091
Directory '/node_modules' does not exist, skipping all lookups in it.
10921092
======== Module name '@typescript/lib-esnext/intl' was not resolved. ========
1093+
======== Resolving module '@typescript/lib-esnext/promise' from '/.src/__lib_node_modules_lookup_lib.esnext.promise.d.ts__.ts'. ========
1094+
Module resolution kind is not specified, using 'Bundler'.
1095+
Resolving in CJS mode with conditions 'require', 'types'.
1096+
File '/.src/package.json' does not exist according to earlier cached lookups.
1097+
File '/package.json' does not exist according to earlier cached lookups.
1098+
Loading module '@typescript/lib-esnext/promise' from 'node_modules' folder, target file types: TypeScript, JavaScript, Declaration, JSON.
1099+
Searching all ancestor node_modules directories for preferred extensions: TypeScript, Declaration.
1100+
Directory '/.src/node_modules' does not exist, skipping all lookups in it.
1101+
Directory '/node_modules' does not exist, skipping all lookups in it.
1102+
Searching all ancestor node_modules directories for fallback extensions: JavaScript, JSON.
1103+
Directory '/.src/node_modules' does not exist, skipping all lookups in it.
1104+
Directory '/node_modules' does not exist, skipping all lookups in it.
1105+
======== Module name '@typescript/lib-esnext/promise' was not resolved. ========
10931106
======== Resolving module '@typescript/lib-esnext/sharedmemory' from '/.src/__lib_node_modules_lookup_lib.esnext.sharedmemory.d.ts__.ts'. ========
10941107
Module resolution kind is not specified, using 'Bundler'.
10951108
Resolving in CJS mode with conditions 'require', 'types'.
Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,72 @@
1+
promiseAllKeyed.ts(50,18): error TS2345: Argument of type 'number' is not assignable to parameter of type 'object'.
2+
promiseAllKeyed.ts(52,25): error TS2345: Argument of type 'string' is not assignable to parameter of type 'object'.
3+
promiseAllKeyed.ts(54,18): error TS2345: Argument of type 'null' is not assignable to parameter of type 'object'.
4+
promiseAllKeyed.ts(56,25): error TS2345: Argument of type 'undefined' is not assignable to parameter of type 'object'.
5+
6+
7+
==== promiseAllKeyed.ts (4 errors) ====
8+
declare const key: unique symbol;
9+
10+
const values = {
11+
a: 1 as number,
12+
b: Promise.resolve("value"),
13+
c: { then(resolve: (value: boolean) => void) { resolve(true); } },
14+
[key]: Promise.resolve(42),
15+
} as const;
16+
17+
async function testAllKeyed() {
18+
const result = await Promise.allKeyed(values);
19+
const a: number = result.a;
20+
const b: string = result.b;
21+
const c: boolean = result.c;
22+
const d: number = result[key];
23+
24+
result.a = 2;
25+
}
26+
27+
async function testAllSettledKeyed() {
28+
const result = await Promise.allSettledKeyed(values);
29+
30+
if (result.b.status === "fulfilled") {
31+
const value: string = result.b.value;
32+
}
33+
else {
34+
const reason: any = result.b.reason;
35+
}
36+
37+
if (result[key].status === "fulfilled") {
38+
const value: number = result[key].value;
39+
}
40+
}
41+
42+
interface Input {
43+
a: Promise<number>;
44+
b: string;
45+
}
46+
47+
declare const input: Input;
48+
49+
const allResult: Promise<{ a: number; b: string; }> = Promise.allKeyed(input);
50+
const allSettledResult: Promise<{
51+
a: PromiseSettledResult<number>;
52+
b: PromiseSettledResult<string>;
53+
}> = Promise.allSettledKeyed(input);
54+
55+
Promise.try(() => 1);
56+
57+
Promise.allKeyed(0);
58+
~
59+
!!! error TS2345: Argument of type 'number' is not assignable to parameter of type 'object'.
60+
61+
Promise.allSettledKeyed("value");
62+
~~~~~~~
63+
!!! error TS2345: Argument of type 'string' is not assignable to parameter of type 'object'.
64+
65+
Promise.allKeyed(null);
66+
~~~~
67+
!!! error TS2345: Argument of type 'null' is not assignable to parameter of type 'object'.
68+
69+
Promise.allSettledKeyed(undefined);
70+
~~~~~~~~~
71+
!!! error TS2345: Argument of type 'undefined' is not assignable to parameter of type 'object'.
72+
Lines changed: 96 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,96 @@
1+
//// [tests/cases/compiler/promiseAllKeyed.ts] ////
2+
3+
//// [promiseAllKeyed.ts]
4+
declare const key: unique symbol;
5+
6+
const values = {
7+
a: 1 as number,
8+
b: Promise.resolve("value"),
9+
c: { then(resolve: (value: boolean) => void) { resolve(true); } },
10+
[key]: Promise.resolve(42),
11+
} as const;
12+
13+
async function testAllKeyed() {
14+
const result = await Promise.allKeyed(values);
15+
const a: number = result.a;
16+
const b: string = result.b;
17+
const c: boolean = result.c;
18+
const d: number = result[key];
19+
20+
result.a = 2;
21+
}
22+
23+
async function testAllSettledKeyed() {
24+
const result = await Promise.allSettledKeyed(values);
25+
26+
if (result.b.status === "fulfilled") {
27+
const value: string = result.b.value;
28+
}
29+
else {
30+
const reason: any = result.b.reason;
31+
}
32+
33+
if (result[key].status === "fulfilled") {
34+
const value: number = result[key].value;
35+
}
36+
}
37+
38+
interface Input {
39+
a: Promise<number>;
40+
b: string;
41+
}
42+
43+
declare const input: Input;
44+
45+
const allResult: Promise<{ a: number; b: string; }> = Promise.allKeyed(input);
46+
const allSettledResult: Promise<{
47+
a: PromiseSettledResult<number>;
48+
b: PromiseSettledResult<string>;
49+
}> = Promise.allSettledKeyed(input);
50+
51+
Promise.try(() => 1);
52+
53+
Promise.allKeyed(0);
54+
55+
Promise.allSettledKeyed("value");
56+
57+
Promise.allKeyed(null);
58+
59+
Promise.allSettledKeyed(undefined);
60+
61+
62+
//// [promiseAllKeyed.js]
63+
"use strict";
64+
const values = {
65+
a: 1,
66+
b: Promise.resolve("value"),
67+
c: { then(resolve) { resolve(true); } },
68+
[key]: Promise.resolve(42),
69+
};
70+
async function testAllKeyed() {
71+
const result = await Promise.allKeyed(values);
72+
const a = result.a;
73+
const b = result.b;
74+
const c = result.c;
75+
const d = result[key];
76+
result.a = 2;
77+
}
78+
async function testAllSettledKeyed() {
79+
const result = await Promise.allSettledKeyed(values);
80+
if (result.b.status === "fulfilled") {
81+
const value = result.b.value;
82+
}
83+
else {
84+
const reason = result.b.reason;
85+
}
86+
if (result[key].status === "fulfilled") {
87+
const value = result[key].value;
88+
}
89+
}
90+
const allResult = Promise.allKeyed(input);
91+
const allSettledResult = Promise.allSettledKeyed(input);
92+
Promise.try(() => 1);
93+
Promise.allKeyed(0);
94+
Promise.allSettledKeyed("value");
95+
Promise.allKeyed(null);
96+
Promise.allSettledKeyed(undefined);

0 commit comments

Comments
 (0)