Skip to content

Commit cecd8c5

Browse files
PimmJaredNeil
andauthored
Make Map constructor argument optional and nullable (microsoft#43396)
* Make Iterable Map constructor argument optional Fixes microsoft#37779 * Change Map constructor in iterable to accept both null and undefined. According to the spec (https://tc39.es/ecma262/#sec-map-iterable), the sole argument passed to Map is allowed to be null or undefined. * Changed Map constructor to ensure new Map() still types as Map<any, any>. * Add map constructor test. This proves that the previous commit fixes microsoft#37779, as well as that new Map() still types as Map<any, any>. * Update baseline. Co-authored-by: Jared Neil <[email protected]>
1 parent 7490b32 commit cecd8c5

8 files changed

+95
-10
lines changed

src/lib/es2015.iterable.d.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -137,7 +137,8 @@ interface ReadonlyMap<K, V> {
137137
}
138138

139139
interface MapConstructor {
140-
new <K, V>(iterable: Iterable<readonly [K, V]>): Map<K, V>;
140+
new(): Map<any, any>;
141+
new <K, V>(iterable?: Iterable<readonly [K, V]> | null): Map<K, V>;
141142
}
142143

143144
interface WeakMap<K extends object, V> { }

tests/baselines/reference/for-of39.errors.txt

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
tests/cases/conformance/es6/for-ofStatements/for-of39.ts(1,11): error TS2769: No overload matches this call.
2-
Overload 1 of 3, '(iterable: Iterable<readonly [string, boolean]>): Map<string, boolean>', gave the following error.
2+
Overload 1 of 4, '(iterable?: Iterable<readonly [string, boolean]>): Map<string, boolean>', gave the following error.
33
Argument of type '([string, number] | [string, true])[]' is not assignable to parameter of type 'Iterable<readonly [string, boolean]>'.
44
The types returned by '[Symbol.iterator]().next(...)' are incompatible between these types.
55
Type 'IteratorResult<[string, number] | [string, true], any>' is not assignable to type 'IteratorResult<readonly [string, boolean], any>'.
@@ -9,15 +9,15 @@ tests/cases/conformance/es6/for-ofStatements/for-of39.ts(1,11): error TS2769: No
99
Type '[string, number]' is not assignable to type 'readonly [string, boolean]'.
1010
Type at position 1 in source is not compatible with type at position 1 in target.
1111
Type 'number' is not assignable to type 'boolean'.
12-
Overload 2 of 3, '(entries?: readonly (readonly [string, boolean])[]): Map<string, boolean>', gave the following error.
12+
Overload 2 of 4, '(entries?: readonly (readonly [string, boolean])[]): Map<string, boolean>', gave the following error.
1313
Type 'number' is not assignable to type 'boolean'.
1414

1515

1616
==== tests/cases/conformance/es6/for-ofStatements/for-of39.ts (1 errors) ====
1717
var map = new Map([["", true], ["", 0]]);
1818
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
1919
!!! error TS2769: No overload matches this call.
20-
!!! error TS2769: Overload 1 of 3, '(iterable: Iterable<readonly [string, boolean]>): Map<string, boolean>', gave the following error.
20+
!!! error TS2769: Overload 1 of 4, '(iterable?: Iterable<readonly [string, boolean]>): Map<string, boolean>', gave the following error.
2121
!!! error TS2769: Argument of type '([string, number] | [string, true])[]' is not assignable to parameter of type 'Iterable<readonly [string, boolean]>'.
2222
!!! error TS2769: The types returned by '[Symbol.iterator]().next(...)' are incompatible between these types.
2323
!!! error TS2769: Type 'IteratorResult<[string, number] | [string, true], any>' is not assignable to type 'IteratorResult<readonly [string, boolean], any>'.
@@ -27,7 +27,7 @@ tests/cases/conformance/es6/for-ofStatements/for-of39.ts(1,11): error TS2769: No
2727
!!! error TS2769: Type '[string, number]' is not assignable to type 'readonly [string, boolean]'.
2828
!!! error TS2769: Type at position 1 in source is not compatible with type at position 1 in target.
2929
!!! error TS2769: Type 'number' is not assignable to type 'boolean'.
30-
!!! error TS2769: Overload 2 of 3, '(entries?: readonly (readonly [string, boolean])[]): Map<string, boolean>', gave the following error.
30+
!!! error TS2769: Overload 2 of 4, '(entries?: readonly (readonly [string, boolean])[]): Map<string, boolean>', gave the following error.
3131
!!! error TS2769: Type 'number' is not assignable to type 'boolean'.
3232
for (var [k, v] of map) {
3333
k;

tests/baselines/reference/iterableArrayPattern28.errors.txt

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
tests/cases/conformance/es6/destructuring/iterableArrayPattern28.ts(2,24): error TS2769: No overload matches this call.
2-
Overload 1 of 3, '(iterable: Iterable<readonly [string, number]>): Map<string, number>', gave the following error.
2+
Overload 1 of 4, '(iterable?: Iterable<readonly [string, number]>): Map<string, number>', gave the following error.
33
Argument of type '([string, number] | [string, boolean])[]' is not assignable to parameter of type 'Iterable<readonly [string, number]>'.
44
The types returned by '[Symbol.iterator]().next(...)' are incompatible between these types.
55
Type 'IteratorResult<[string, number] | [string, boolean], any>' is not assignable to type 'IteratorResult<readonly [string, number], any>'.
@@ -9,7 +9,7 @@ tests/cases/conformance/es6/destructuring/iterableArrayPattern28.ts(2,24): error
99
Type '[string, boolean]' is not assignable to type 'readonly [string, number]'.
1010
Type at position 1 in source is not compatible with type at position 1 in target.
1111
Type 'boolean' is not assignable to type 'number'.
12-
Overload 2 of 3, '(entries?: readonly (readonly [string, number])[]): Map<string, number>', gave the following error.
12+
Overload 2 of 4, '(entries?: readonly (readonly [string, number])[]): Map<string, number>', gave the following error.
1313
Type 'boolean' is not assignable to type 'number'.
1414

1515

@@ -18,7 +18,7 @@ tests/cases/conformance/es6/destructuring/iterableArrayPattern28.ts(2,24): error
1818
takeFirstTwoEntries(...new Map([["", 0], ["hello", true]]));
1919
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
2020
!!! error TS2769: No overload matches this call.
21-
!!! error TS2769: Overload 1 of 3, '(iterable: Iterable<readonly [string, number]>): Map<string, number>', gave the following error.
21+
!!! error TS2769: Overload 1 of 4, '(iterable?: Iterable<readonly [string, number]>): Map<string, number>', gave the following error.
2222
!!! error TS2769: Argument of type '([string, number] | [string, boolean])[]' is not assignable to parameter of type 'Iterable<readonly [string, number]>'.
2323
!!! error TS2769: The types returned by '[Symbol.iterator]().next(...)' are incompatible between these types.
2424
!!! error TS2769: Type 'IteratorResult<[string, number] | [string, boolean], any>' is not assignable to type 'IteratorResult<readonly [string, number], any>'.
@@ -28,5 +28,5 @@ tests/cases/conformance/es6/destructuring/iterableArrayPattern28.ts(2,24): error
2828
!!! error TS2769: Type '[string, boolean]' is not assignable to type 'readonly [string, number]'.
2929
!!! error TS2769: Type at position 1 in source is not compatible with type at position 1 in target.
3030
!!! error TS2769: Type 'boolean' is not assignable to type 'number'.
31-
!!! error TS2769: Overload 2 of 3, '(entries?: readonly (readonly [string, number])[]): Map<string, number>', gave the following error.
31+
!!! error TS2769: Overload 2 of 4, '(entries?: readonly (readonly [string, number])[]): Map<string, number>', gave the following error.
3232
!!! error TS2769: Type 'boolean' is not assignable to type 'number'.
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
//// [mapConstructor.ts]
2+
new Map();
3+
4+
const potentiallyUndefinedIterable = [['1', 1], ['2', 2]] as Iterable<[string, number]> | undefined;
5+
new Map(potentiallyUndefinedIterable);
6+
7+
const potentiallyNullIterable = [['1', 1], ['2', 2]] as Iterable<[string, number]> | null;
8+
new Map(potentiallyNullIterable);
9+
10+
//// [mapConstructor.js]
11+
"use strict";
12+
new Map();
13+
const potentiallyUndefinedIterable = [['1', 1], ['2', 2]];
14+
new Map(potentiallyUndefinedIterable);
15+
const potentiallyNullIterable = [['1', 1], ['2', 2]];
16+
new Map(potentiallyNullIterable);
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
=== tests/cases/compiler/mapConstructor.ts ===
2+
new Map();
3+
>Map : Symbol(Map, Decl(lib.es2015.collection.d.ts, --, --), Decl(lib.es2015.collection.d.ts, --, --), Decl(lib.es2015.iterable.d.ts, --, --), Decl(lib.es2015.symbol.wellknown.d.ts, --, --))
4+
5+
const potentiallyUndefinedIterable = [['1', 1], ['2', 2]] as Iterable<[string, number]> | undefined;
6+
>potentiallyUndefinedIterable : Symbol(potentiallyUndefinedIterable, Decl(mapConstructor.ts, 2, 5))
7+
>Iterable : Symbol(Iterable, Decl(lib.es2015.iterable.d.ts, --, --))
8+
9+
new Map(potentiallyUndefinedIterable);
10+
>Map : Symbol(Map, Decl(lib.es2015.collection.d.ts, --, --), Decl(lib.es2015.collection.d.ts, --, --), Decl(lib.es2015.iterable.d.ts, --, --), Decl(lib.es2015.symbol.wellknown.d.ts, --, --))
11+
>potentiallyUndefinedIterable : Symbol(potentiallyUndefinedIterable, Decl(mapConstructor.ts, 2, 5))
12+
13+
const potentiallyNullIterable = [['1', 1], ['2', 2]] as Iterable<[string, number]> | null;
14+
>potentiallyNullIterable : Symbol(potentiallyNullIterable, Decl(mapConstructor.ts, 5, 5))
15+
>Iterable : Symbol(Iterable, Decl(lib.es2015.iterable.d.ts, --, --))
16+
17+
new Map(potentiallyNullIterable);
18+
>Map : Symbol(Map, Decl(lib.es2015.collection.d.ts, --, --), Decl(lib.es2015.collection.d.ts, --, --), Decl(lib.es2015.iterable.d.ts, --, --), Decl(lib.es2015.symbol.wellknown.d.ts, --, --))
19+
>potentiallyNullIterable : Symbol(potentiallyNullIterable, Decl(mapConstructor.ts, 5, 5))
20+
Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
=== tests/cases/compiler/mapConstructor.ts ===
2+
new Map();
3+
>new Map() : Map<any, any>
4+
>Map : MapConstructor
5+
6+
const potentiallyUndefinedIterable = [['1', 1], ['2', 2]] as Iterable<[string, number]> | undefined;
7+
>potentiallyUndefinedIterable : Iterable<[string, number]> | undefined
8+
>[['1', 1], ['2', 2]] as Iterable<[string, number]> | undefined : Iterable<[string, number]> | undefined
9+
>[['1', 1], ['2', 2]] : [string, number][]
10+
>['1', 1] : [string, number]
11+
>'1' : "1"
12+
>1 : 1
13+
>['2', 2] : [string, number]
14+
>'2' : "2"
15+
>2 : 2
16+
17+
new Map(potentiallyUndefinedIterable);
18+
>new Map(potentiallyUndefinedIterable) : Map<string, number>
19+
>Map : MapConstructor
20+
>potentiallyUndefinedIterable : Iterable<[string, number]> | undefined
21+
22+
const potentiallyNullIterable = [['1', 1], ['2', 2]] as Iterable<[string, number]> | null;
23+
>potentiallyNullIterable : Iterable<[string, number]> | null
24+
>[['1', 1], ['2', 2]] as Iterable<[string, number]> | null : Iterable<[string, number]> | null
25+
>[['1', 1], ['2', 2]] : [string, number][]
26+
>['1', 1] : [string, number]
27+
>'1' : "1"
28+
>1 : 1
29+
>['2', 2] : [string, number]
30+
>'2' : "2"
31+
>2 : 2
32+
>null : null
33+
34+
new Map(potentiallyNullIterable);
35+
>new Map(potentiallyNullIterable) : Map<string, number>
36+
>Map : MapConstructor
37+
>potentiallyNullIterable : Iterable<[string, number]> | null
38+
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
=== tests/cases/compiler/newMap.ts ===
22
new Map<string>();
3-
>new Map<string>() : Map<string, unknown>
3+
>new Map<string>() : Map<any, any>
44
>Map : MapConstructor
55

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
// @strict: true
2+
// @target: es2015
3+
4+
new Map();
5+
6+
const potentiallyUndefinedIterable = [['1', 1], ['2', 2]] as Iterable<[string, number]> | undefined;
7+
new Map(potentiallyUndefinedIterable);
8+
9+
const potentiallyNullIterable = [['1', 1], ['2', 2]] as Iterable<[string, number]> | null;
10+
new Map(potentiallyNullIterable);

0 commit comments

Comments
 (0)