From 2e88cc633c1a28dbe7136c078f9cd07c50a21526 Mon Sep 17 00:00:00 2001 From: Dave van Soest Date: Wed, 21 Oct 2026 16:02:39 +0200 Subject: [PATCH 1/7] test: add map constructor test cases exposing the type bug --- .../reference/conformance/new-Map1.errors.txt | 89 +++++++++++++ .../reference/conformance/new-Map1.js | 46 +++++++ .../reference/conformance/new-Map1.symbols | 61 +++++++++ .../reference/conformance/new-Map1.types | 119 ++++++++++++++++++ .../es6/mapConstruction/new-Map1.ts | 21 ++++ 5 files changed, 336 insertions(+) create mode 100644 tsc/testdata/baselines/reference/conformance/new-Map1.errors.txt create mode 100644 tsc/testdata/baselines/reference/conformance/new-Map1.js create mode 100644 tsc/testdata/baselines/reference/conformance/new-Map1.symbols create mode 100644 tsc/testdata/baselines/reference/conformance/new-Map1.types create mode 100644 tsc/testdata/tests/cases/conformance/es6/mapConstruction/new-Map1.ts diff --git a/tsc/testdata/baselines/reference/conformance/new-Map1.errors.txt b/tsc/testdata/baselines/reference/conformance/new-Map1.errors.txt new file mode 100644 index 0000000000000..c9a6805d8415b --- /dev/null +++ b/tsc/testdata/baselines/reference/conformance/new-Map1.errors.txt @@ -0,0 +1,89 @@ +new-Map1.ts(2,56): error TS2769: No overload matches this call. + The last overload gave the following error. + Type 'number' is not assignable to type 'string'. +new-Map1.ts(6,32): error TS2769: No overload matches this call. + The last overload gave the following error. + Type 'number' is not assignable to type 'string'. +new-Map1.ts(14,2): error TS2769: No overload matches this call. + The last overload gave the following error. + Type '[string, { a: number; b: string; }] | [string, { a: number; }]' is not assignable to type 'readonly [string, { a: number; b: string; }]'. + Type '[string, { a: number; }]' is not assignable to type 'readonly [string, { a: number; b: string; }]'. + Type at position 1 in source is not compatible with type at position 1 in target. + Property 'b' is missing in type '{ a: number; }' but required in type '{ a: number; b: string; }'. +new-Map1.ts(15,8): error TS2769: No overload matches this call. + The last overload gave the following error. + Property 'b' is missing in type '{ a: number; }' but required in type '{ a: number; b: string; }'. +new-Map1.ts(19,29): error TS2769: No overload matches this call. + The last overload gave the following error. + Type 'number' is not assignable to type 'string'. +new-Map1.ts(20,43): error TS2769: No overload matches this call. + The last overload gave the following error. + Type '"val2"' is not assignable to type '456'. +new-Map1.ts(21,61): error TS2769: No overload matches this call. + The last overload gave the following error. + Type 'string' is not assignable to type 'number'. + + +==== new-Map1.ts (7 errors) ==== + // https://github.com/microsoft/TypeScript/issues/37527#issuecomment-628802102 + const sample: Map = new Map([[1, 1], ["yes", 1]]); + ~ +!!! error TS2769: No overload matches this call. +!!! error TS2769: The last overload gave the following error. +!!! error TS2769: Type 'number' is not assignable to type 'string'. +!!! related TS2771 lib.es2015.collection.d.ts:--:--: The last overload is declared here. + + // https://github.com/microsoft/TypeScript/issues/37527#issuecomment-750412755 + function test(_a: Map) {} + test(new Map([["test" ,true] ,[1 ,false]])) + ~ +!!! error TS2769: No overload matches this call. +!!! error TS2769: The last overload gave the following error. +!!! error TS2769: Type 'number' is not assignable to type 'string'. +!!! related TS2771 lib.es2015.collection.d.ts:--:--: The last overload is declared here. + + // https://github.com/microsoft/TypeScript/issues/33611#issue-498858215 + const M1 = new Map([ + ['k', {a: 1, b: 'asd'}], + ['k', {a: 2, b: 'asd'}], + ]); + const M2 = new Map([ + ...M1, + ~~~~~ +!!! error TS2769: No overload matches this call. +!!! error TS2769: The last overload gave the following error. +!!! error TS2769: Type '[string, { a: number; b: string; }] | [string, { a: number; }]' is not assignable to type 'readonly [string, { a: number; b: string; }]'. +!!! error TS2769: Type '[string, { a: number; }]' is not assignable to type 'readonly [string, { a: number; b: string; }]'. +!!! error TS2769: Type at position 1 in source is not compatible with type at position 1 in target. +!!! error TS2769: Property 'b' is missing in type '{ a: number; }' but required in type '{ a: number; b: string; }'. +!!! related TS2728 new-Map1.ts:10:15: 'b' is declared here. +!!! related TS2771 lib.es2015.collection.d.ts:--:--: The last overload is declared here. + ['k', {a: 1}], + ~~~~~~ +!!! error TS2769: No overload matches this call. +!!! error TS2769: The last overload gave the following error. +!!! error TS2769: Property 'b' is missing in type '{ a: number; }' but required in type '{ a: number; b: string; }'. +!!! related TS2728 new-Map1.ts:10:15: 'b' is declared here. +!!! related TS2771 lib.es2015.collection.d.ts:--:--: The last overload is declared here. + ]); + + // Additional cases + const m1 = new Map([['num', 123], ['str', 'val1']]); + ~~~ +!!! error TS2769: No overload matches this call. +!!! error TS2769: The last overload gave the following error. +!!! error TS2769: Type 'number' is not assignable to type 'string'. +!!! related TS2771 lib.es2015.collection.d.ts:--:--: The last overload is declared here. + const m2 = new Map([['num', 456], ['str', 'val2']] as const); + ~~~~~~ +!!! error TS2769: No overload matches this call. +!!! error TS2769: The last overload gave the following error. +!!! error TS2769: Type '"val2"' is not assignable to type '456'. +!!! related TS2771 lib.es2015.collection.d.ts:--:--: The last overload is declared here. + const m3 = new Map([['num' as const, 456], ['str' as const, 'val2']]); + ~~~~~~ +!!! error TS2769: No overload matches this call. +!!! error TS2769: The last overload gave the following error. +!!! error TS2769: Type 'string' is not assignable to type 'number'. +!!! related TS2771 lib.es2015.collection.d.ts:--:--: The last overload is declared here. + \ No newline at end of file diff --git a/tsc/testdata/baselines/reference/conformance/new-Map1.js b/tsc/testdata/baselines/reference/conformance/new-Map1.js new file mode 100644 index 0000000000000..53c665e92be81 --- /dev/null +++ b/tsc/testdata/baselines/reference/conformance/new-Map1.js @@ -0,0 +1,46 @@ +//// [tests/cases/conformance/es6/mapConstruction/new-Map1.ts] //// + +//// [new-Map1.ts] +// https://github.com/microsoft/TypeScript/issues/37527#issuecomment-628802102 +const sample: Map = new Map([[1, 1], ["yes", 1]]); + +// https://github.com/microsoft/TypeScript/issues/37527#issuecomment-750412755 +function test(_a: Map) {} +test(new Map([["test" ,true] ,[1 ,false]])) + +// https://github.com/microsoft/TypeScript/issues/33611#issue-498858215 +const M1 = new Map([ + ['k', {a: 1, b: 'asd'}], + ['k', {a: 2, b: 'asd'}], +]); +const M2 = new Map([ + ...M1, + ['k', {a: 1}], +]); + +// Additional cases +const m1 = new Map([['num', 123], ['str', 'val1']]); +const m2 = new Map([['num', 456], ['str', 'val2']] as const); +const m3 = new Map([['num' as const, 456], ['str' as const, 'val2']]); + + +//// [new-Map1.js] +"use strict"; +// https://github.com/microsoft/TypeScript/issues/37527#issuecomment-628802102 +const sample = new Map([[1, 1], ["yes", 1]]); +// https://github.com/microsoft/TypeScript/issues/37527#issuecomment-750412755 +function test(_a) { } +test(new Map([["test", true], [1, false]])); +// https://github.com/microsoft/TypeScript/issues/33611#issue-498858215 +const M1 = new Map([ + ['k', { a: 1, b: 'asd' }], + ['k', { a: 2, b: 'asd' }], +]); +const M2 = new Map([ + ...M1, + ['k', { a: 1 }], +]); +// Additional cases +const m1 = new Map([['num', 123], ['str', 'val1']]); +const m2 = new Map([['num', 456], ['str', 'val2']]); +const m3 = new Map([['num', 456], ['str', 'val2']]); diff --git a/tsc/testdata/baselines/reference/conformance/new-Map1.symbols b/tsc/testdata/baselines/reference/conformance/new-Map1.symbols new file mode 100644 index 0000000000000..74a3315139ed7 --- /dev/null +++ b/tsc/testdata/baselines/reference/conformance/new-Map1.symbols @@ -0,0 +1,61 @@ +//// [tests/cases/conformance/es6/mapConstruction/new-Map1.ts] //// + +=== new-Map1.ts === +// https://github.com/microsoft/TypeScript/issues/37527#issuecomment-628802102 +const sample: Map = new Map([[1, 1], ["yes", 1]]); +>sample : Symbol(sample, Decl(new-Map1.ts, 1, 5)) +>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, --, --), Decl(lib.es2026.collection.d.ts, --, --)) +>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, --, --), Decl(lib.es2026.collection.d.ts, --, --)) + +// https://github.com/microsoft/TypeScript/issues/37527#issuecomment-750412755 +function test(_a: Map) {} +>test : Symbol(test, Decl(new-Map1.ts, 1, 75)) +>_a : Symbol(_a, Decl(new-Map1.ts, 4, 14)) +>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, --, --), Decl(lib.es2026.collection.d.ts, --, --)) + +test(new Map([["test" ,true] ,[1 ,false]])) +>test : Symbol(test, Decl(new-Map1.ts, 1, 75)) +>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, --, --), Decl(lib.es2026.collection.d.ts, --, --)) + +// https://github.com/microsoft/TypeScript/issues/33611#issue-498858215 +const M1 = new Map([ +>M1 : Symbol(M1, Decl(new-Map1.ts, 8, 5)) +>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, --, --), Decl(lib.es2026.collection.d.ts, --, --)) + + ['k', {a: 1, b: 'asd'}], +>a : Symbol(a, Decl(new-Map1.ts, 9, 8)) +>b : Symbol(b, Decl(new-Map1.ts, 9, 13)) + + ['k', {a: 2, b: 'asd'}], +>a : Symbol(a, Decl(new-Map1.ts, 10, 8)) +>b : Symbol(b, Decl(new-Map1.ts, 10, 13)) + +]); +const M2 = new Map([ +>M2 : Symbol(M2, Decl(new-Map1.ts, 12, 5)) +>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, --, --), Decl(lib.es2026.collection.d.ts, --, --)) + + ...M1, +>M1 : Symbol(M1, Decl(new-Map1.ts, 8, 5)) + + ['k', {a: 1}], +>a : Symbol(a, Decl(new-Map1.ts, 14, 8)) + +]); + +// Additional cases +const m1 = new Map([['num', 123], ['str', 'val1']]); +>m1 : Symbol(m1, Decl(new-Map1.ts, 18, 5)) +>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, --, --), Decl(lib.es2026.collection.d.ts, --, --)) + +const m2 = new Map([['num', 456], ['str', 'val2']] as const); +>m2 : Symbol(m2, Decl(new-Map1.ts, 19, 5)) +>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, --, --), Decl(lib.es2026.collection.d.ts, --, --)) +>const : Symbol(const) + +const m3 = new Map([['num' as const, 456], ['str' as const, 'val2']]); +>m3 : Symbol(m3, Decl(new-Map1.ts, 20, 5)) +>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, --, --), Decl(lib.es2026.collection.d.ts, --, --)) +>const : Symbol(const) +>const : Symbol(const) + diff --git a/tsc/testdata/baselines/reference/conformance/new-Map1.types b/tsc/testdata/baselines/reference/conformance/new-Map1.types new file mode 100644 index 0000000000000..eab380f1f2c97 --- /dev/null +++ b/tsc/testdata/baselines/reference/conformance/new-Map1.types @@ -0,0 +1,119 @@ +//// [tests/cases/conformance/es6/mapConstruction/new-Map1.ts] //// + +=== new-Map1.ts === +// https://github.com/microsoft/TypeScript/issues/37527#issuecomment-628802102 +const sample: Map = new Map([[1, 1], ["yes", 1]]); +>sample : Map +>new Map([[1, 1], ["yes", 1]]) : Map +>Map : MapConstructor +>[[1, 1], ["yes", 1]] : ([string, number] | [number, number])[] +>[1, 1] : [number, number] +>1 : 1 +>1 : 1 +>["yes", 1] : [string, number] +>"yes" : "yes" +>1 : 1 + +// https://github.com/microsoft/TypeScript/issues/37527#issuecomment-750412755 +function test(_a: Map) {} +>test : (_a: Map) => void +>_a : Map + +test(new Map([["test" ,true] ,[1 ,false]])) +>test(new Map([["test" ,true] ,[1 ,false]])) : void +>test : (_a: Map) => void +>new Map([["test" ,true] ,[1 ,false]]) : Map +>Map : MapConstructor +>[["test" ,true] ,[1 ,false]] : ([string, true] | [number, false])[] +>["test" ,true] : [string, true] +>"test" : "test" +>true : true +>[1 ,false] : [number, false] +>1 : 1 +>false : false + +// https://github.com/microsoft/TypeScript/issues/33611#issue-498858215 +const M1 = new Map([ +>M1 : Map +>new Map([ ['k', {a: 1, b: 'asd'}], ['k', {a: 2, b: 'asd'}],]) : Map +>Map : MapConstructor +>[ ['k', {a: 1, b: 'asd'}], ['k', {a: 2, b: 'asd'}],] : [string, { a: number; b: string; }][] + + ['k', {a: 1, b: 'asd'}], +>['k', {a: 1, b: 'asd'}] : [string, { a: number; b: string; }] +>'k' : "k" +>{a: 1, b: 'asd'} : { a: number; b: string; } +>a : number +>1 : 1 +>b : string +>'asd' : "asd" + + ['k', {a: 2, b: 'asd'}], +>['k', {a: 2, b: 'asd'}] : [string, { a: number; b: string; }] +>'k' : "k" +>{a: 2, b: 'asd'} : { a: number; b: string; } +>a : number +>2 : 2 +>b : string +>'asd' : "asd" + +]); +const M2 = new Map([ +>M2 : Map +>new Map([ ...M1, ['k', {a: 1}],]) : Map +>Map : MapConstructor +>[ ...M1, ['k', {a: 1}],] : ([string, { a: number; b: string; }] | [string, { a: number; }])[] + + ...M1, +>...M1 : [string, { a: number; b: string; }] +>M1 : Map + + ['k', {a: 1}], +>['k', {a: 1}] : [string, { a: number; }] +>'k' : "k" +>{a: 1} : { a: number; } +>a : number +>1 : 1 + +]); + +// Additional cases +const m1 = new Map([['num', 123], ['str', 'val1']]); +>m1 : Map +>new Map([['num', 123], ['str', 'val1']]) : Map +>Map : MapConstructor +>[['num', 123], ['str', 'val1']] : ([string, string] | [string, number])[] +>['num', 123] : [string, number] +>'num' : "num" +>123 : 123 +>['str', 'val1'] : [string, string] +>'str' : "str" +>'val1' : "val1" + +const m2 = new Map([['num', 456], ['str', 'val2']] as const); +>m2 : Map<"num" | "str", 456> +>new Map([['num', 456], ['str', 'val2']] as const) : Map<"num" | "str", 456> +>Map : MapConstructor +>[['num', 456], ['str', 'val2']] as const : readonly [readonly ["num", 456], readonly ["str", "val2"]] +>[['num', 456], ['str', 'val2']] : readonly [readonly ["num", 456], readonly ["str", "val2"]] +>['num', 456] : readonly ["num", 456] +>'num' : "num" +>456 : 456 +>['str', 'val2'] : readonly ["str", "val2"] +>'str' : "str" +>'val2' : "val2" + +const m3 = new Map([['num' as const, 456], ['str' as const, 'val2']]); +>m3 : Map<"num" | "str", number> +>new Map([['num' as const, 456], ['str' as const, 'val2']]) : Map<"num" | "str", number> +>Map : MapConstructor +>[['num' as const, 456], ['str' as const, 'val2']] : (["num", number] | ["str", string])[] +>['num' as const, 456] : ["num", number] +>'num' as const : "num" +>'num' : "num" +>456 : 456 +>['str' as const, 'val2'] : ["str", string] +>'str' as const : "str" +>'str' : "str" +>'val2' : "val2" + diff --git a/tsc/testdata/tests/cases/conformance/es6/mapConstruction/new-Map1.ts b/tsc/testdata/tests/cases/conformance/es6/mapConstruction/new-Map1.ts new file mode 100644 index 0000000000000..d97e848cbc0ef --- /dev/null +++ b/tsc/testdata/tests/cases/conformance/es6/mapConstruction/new-Map1.ts @@ -0,0 +1,21 @@ +// https://github.com/microsoft/TypeScript/issues/37527#issuecomment-628802102 +const sample: Map = new Map([[1, 1], ["yes", 1]]); + +// https://github.com/microsoft/TypeScript/issues/37527#issuecomment-750412755 +function test(_a: Map) {} +test(new Map([["test" ,true] ,[1 ,false]])) + +// https://github.com/microsoft/TypeScript/issues/33611#issue-498858215 +const M1 = new Map([ + ['k', {a: 1, b: 'asd'}], + ['k', {a: 2, b: 'asd'}], +]); +const M2 = new Map([ + ...M1, + ['k', {a: 1}], +]); + +// Additional cases +const m1 = new Map([['num', 123], ['str', 'val1']]); +const m2 = new Map([['num', 456], ['str', 'val2']] as const); +const m3 = new Map([['num' as const, 456], ['str' as const, 'val2']]); From 3e1a1669669e7835838040f4ea034f0a7e93c046 Mon Sep 17 00:00:00 2001 From: Dave van Soest Date: Wed, 21 Oct 2026 16:09:10 +0200 Subject: [PATCH 2/7] fix: correct map constructor hetegeneous type inference --- .../bundled/libs/lib.es2015.collection.d.ts | 1 + .../reference/compiler/newMap.errors.txt | 4 +- .../reference/conformance/for-of39.errors.txt | 16 ---- .../reference/conformance/for-of39.types | 14 +-- .../iterableArrayPattern28.errors.txt | 17 ++-- .../conformance/iterableArrayPattern28.types | 8 +- .../reference/conformance/new-Map1.errors.txt | 89 ------------------- .../reference/conformance/new-Map1.types | 20 ++--- 8 files changed, 33 insertions(+), 136 deletions(-) delete mode 100644 tsc/testdata/baselines/reference/conformance/for-of39.errors.txt delete mode 100644 tsc/testdata/baselines/reference/conformance/new-Map1.errors.txt diff --git a/tsc/internal/bundled/libs/lib.es2015.collection.d.ts b/tsc/internal/bundled/libs/lib.es2015.collection.d.ts index 225e918b76477..1bd13d6cd4539 100644 --- a/tsc/internal/bundled/libs/lib.es2015.collection.d.ts +++ b/tsc/internal/bundled/libs/lib.es2015.collection.d.ts @@ -48,6 +48,7 @@ interface Map { interface MapConstructor { new (): Map; + new (entries?: KVEntries | null): Map; new (entries?: readonly (readonly [K, V])[] | null): Map; readonly prototype: Map; } diff --git a/tsc/testdata/baselines/reference/compiler/newMap.errors.txt b/tsc/testdata/baselines/reference/compiler/newMap.errors.txt index ac5cce1f5ed80..8bb425f911762 100644 --- a/tsc/testdata/baselines/reference/compiler/newMap.errors.txt +++ b/tsc/testdata/baselines/reference/compiler/newMap.errors.txt @@ -1,9 +1,9 @@ -newMap.ts(1,9): error TS2743: No overload expects 1 type arguments, but overloads do exist that expect either 0 or 2 type arguments. +newMap.ts(1,9): error TS2344: Type 'string' does not satisfy the constraint 'readonly (readonly [any, any])[]'. ==== newMap.ts (1 errors) ==== new Map(); ~~~~~~ -!!! error TS2743: No overload expects 1 type arguments, but overloads do exist that expect either 0 or 2 type arguments. +!!! error TS2344: Type 'string' does not satisfy the constraint 'readonly (readonly [any, any])[]'. new WeakMap(); \ No newline at end of file diff --git a/tsc/testdata/baselines/reference/conformance/for-of39.errors.txt b/tsc/testdata/baselines/reference/conformance/for-of39.errors.txt deleted file mode 100644 index 9b25b5eb78a78..0000000000000 --- a/tsc/testdata/baselines/reference/conformance/for-of39.errors.txt +++ /dev/null @@ -1,16 +0,0 @@ -for-of39.ts(1,25): error TS2769: No overload matches this call. - The last overload gave the following error. - Type 'boolean' is not assignable to type 'number'. - - -==== for-of39.ts (1 errors) ==== - var map = new Map([["", true], ["", 0]]); - ~~~~ -!!! error TS2769: No overload matches this call. -!!! error TS2769: The last overload gave the following error. -!!! error TS2769: Type 'boolean' is not assignable to type 'number'. -!!! related TS2771 lib.es2015.collection.d.ts:--:--: The last overload is declared here. - for (var [k, v] of map) { - k; - v; - } \ No newline at end of file diff --git a/tsc/testdata/baselines/reference/conformance/for-of39.types b/tsc/testdata/baselines/reference/conformance/for-of39.types index 220f0474230f1..f42a6f133cdde 100644 --- a/tsc/testdata/baselines/reference/conformance/for-of39.types +++ b/tsc/testdata/baselines/reference/conformance/for-of39.types @@ -2,11 +2,11 @@ === for-of39.ts === var map = new Map([["", true], ["", 0]]); ->map : Map ->new Map([["", true], ["", 0]]) : Map +>map : Map +>new Map([["", true], ["", 0]]) : Map >Map : MapConstructor ->[["", true], ["", 0]] : ([string, number] | [string, boolean])[] ->["", true] : [string, boolean] +>[["", true], ["", 0]] : ([string, number] | [string, true])[] +>["", true] : [string, true] >"" : "" >true : true >["", 0] : [string, number] @@ -15,12 +15,12 @@ var map = new Map([["", true], ["", 0]]); for (var [k, v] of map) { >k : string ->v : number ->map : Map +>v : number | boolean +>map : Map k; >k : string v; ->v : number +>v : number | boolean } diff --git a/tsc/testdata/baselines/reference/conformance/iterableArrayPattern28.errors.txt b/tsc/testdata/baselines/reference/conformance/iterableArrayPattern28.errors.txt index 23d0eab3af01e..9fd23f7e97209 100644 --- a/tsc/testdata/baselines/reference/conformance/iterableArrayPattern28.errors.txt +++ b/tsc/testdata/baselines/reference/conformance/iterableArrayPattern28.errors.txt @@ -1,13 +1,14 @@ -iterableArrayPattern28.ts(2,52): error TS2769: No overload matches this call. - The last overload gave the following error. - Type 'boolean' is not assignable to type 'number'. +iterableArrayPattern28.ts(2,21): error TS2345: Argument of type '[string, number | boolean]' is not assignable to parameter of type '[string, number]'. + Type at position 1 in source is not compatible with type at position 1 in target. + Type 'number | boolean' is not assignable to type 'number'. + Type 'boolean' is not assignable to type 'number'. ==== iterableArrayPattern28.ts (1 errors) ==== function takeFirstTwoEntries(...[[k1, v1], [k2, v2]]: [string, number][]) { } takeFirstTwoEntries(...new Map([["", 0], ["hello", true]])); - ~~~~ -!!! error TS2769: No overload matches this call. -!!! error TS2769: The last overload gave the following error. -!!! error TS2769: Type 'boolean' is not assignable to type 'number'. -!!! related TS2771 lib.es2015.collection.d.ts:--:--: The last overload is declared here. \ No newline at end of file + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +!!! error TS2345: Argument of type '[string, number | boolean]' is not assignable to parameter of type '[string, number]'. +!!! error TS2345: Type at position 1 in source is not compatible with type at position 1 in target. +!!! error TS2345: Type 'number | boolean' is not assignable to type 'number'. +!!! error TS2345: Type 'boolean' is not assignable to type 'number'. \ No newline at end of file diff --git a/tsc/testdata/baselines/reference/conformance/iterableArrayPattern28.types b/tsc/testdata/baselines/reference/conformance/iterableArrayPattern28.types index 2d836c6eab74d..b833ab983fece 100644 --- a/tsc/testdata/baselines/reference/conformance/iterableArrayPattern28.types +++ b/tsc/testdata/baselines/reference/conformance/iterableArrayPattern28.types @@ -11,14 +11,14 @@ function takeFirstTwoEntries(...[[k1, v1], [k2, v2]]: [string, number][]) { } takeFirstTwoEntries(...new Map([["", 0], ["hello", true]])); >takeFirstTwoEntries(...new Map([["", 0], ["hello", true]])) : void >takeFirstTwoEntries : (...[[k1, v1], [k2, v2]]: [string, number][]) => void ->...new Map([["", 0], ["hello", true]]) : [string, number] ->new Map([["", 0], ["hello", true]]) : Map +>...new Map([["", 0], ["hello", true]]) : [string, number | boolean] +>new Map([["", 0], ["hello", true]]) : Map >Map : MapConstructor ->[["", 0], ["hello", true]] : ([string, number] | [string, boolean])[] +>[["", 0], ["hello", true]] : ([string, number] | [string, true])[] >["", 0] : [string, number] >"" : "" >0 : 0 ->["hello", true] : [string, boolean] +>["hello", true] : [string, true] >"hello" : "hello" >true : true diff --git a/tsc/testdata/baselines/reference/conformance/new-Map1.errors.txt b/tsc/testdata/baselines/reference/conformance/new-Map1.errors.txt deleted file mode 100644 index c9a6805d8415b..0000000000000 --- a/tsc/testdata/baselines/reference/conformance/new-Map1.errors.txt +++ /dev/null @@ -1,89 +0,0 @@ -new-Map1.ts(2,56): error TS2769: No overload matches this call. - The last overload gave the following error. - Type 'number' is not assignable to type 'string'. -new-Map1.ts(6,32): error TS2769: No overload matches this call. - The last overload gave the following error. - Type 'number' is not assignable to type 'string'. -new-Map1.ts(14,2): error TS2769: No overload matches this call. - The last overload gave the following error. - Type '[string, { a: number; b: string; }] | [string, { a: number; }]' is not assignable to type 'readonly [string, { a: number; b: string; }]'. - Type '[string, { a: number; }]' is not assignable to type 'readonly [string, { a: number; b: string; }]'. - Type at position 1 in source is not compatible with type at position 1 in target. - Property 'b' is missing in type '{ a: number; }' but required in type '{ a: number; b: string; }'. -new-Map1.ts(15,8): error TS2769: No overload matches this call. - The last overload gave the following error. - Property 'b' is missing in type '{ a: number; }' but required in type '{ a: number; b: string; }'. -new-Map1.ts(19,29): error TS2769: No overload matches this call. - The last overload gave the following error. - Type 'number' is not assignable to type 'string'. -new-Map1.ts(20,43): error TS2769: No overload matches this call. - The last overload gave the following error. - Type '"val2"' is not assignable to type '456'. -new-Map1.ts(21,61): error TS2769: No overload matches this call. - The last overload gave the following error. - Type 'string' is not assignable to type 'number'. - - -==== new-Map1.ts (7 errors) ==== - // https://github.com/microsoft/TypeScript/issues/37527#issuecomment-628802102 - const sample: Map = new Map([[1, 1], ["yes", 1]]); - ~ -!!! error TS2769: No overload matches this call. -!!! error TS2769: The last overload gave the following error. -!!! error TS2769: Type 'number' is not assignable to type 'string'. -!!! related TS2771 lib.es2015.collection.d.ts:--:--: The last overload is declared here. - - // https://github.com/microsoft/TypeScript/issues/37527#issuecomment-750412755 - function test(_a: Map) {} - test(new Map([["test" ,true] ,[1 ,false]])) - ~ -!!! error TS2769: No overload matches this call. -!!! error TS2769: The last overload gave the following error. -!!! error TS2769: Type 'number' is not assignable to type 'string'. -!!! related TS2771 lib.es2015.collection.d.ts:--:--: The last overload is declared here. - - // https://github.com/microsoft/TypeScript/issues/33611#issue-498858215 - const M1 = new Map([ - ['k', {a: 1, b: 'asd'}], - ['k', {a: 2, b: 'asd'}], - ]); - const M2 = new Map([ - ...M1, - ~~~~~ -!!! error TS2769: No overload matches this call. -!!! error TS2769: The last overload gave the following error. -!!! error TS2769: Type '[string, { a: number; b: string; }] | [string, { a: number; }]' is not assignable to type 'readonly [string, { a: number; b: string; }]'. -!!! error TS2769: Type '[string, { a: number; }]' is not assignable to type 'readonly [string, { a: number; b: string; }]'. -!!! error TS2769: Type at position 1 in source is not compatible with type at position 1 in target. -!!! error TS2769: Property 'b' is missing in type '{ a: number; }' but required in type '{ a: number; b: string; }'. -!!! related TS2728 new-Map1.ts:10:15: 'b' is declared here. -!!! related TS2771 lib.es2015.collection.d.ts:--:--: The last overload is declared here. - ['k', {a: 1}], - ~~~~~~ -!!! error TS2769: No overload matches this call. -!!! error TS2769: The last overload gave the following error. -!!! error TS2769: Property 'b' is missing in type '{ a: number; }' but required in type '{ a: number; b: string; }'. -!!! related TS2728 new-Map1.ts:10:15: 'b' is declared here. -!!! related TS2771 lib.es2015.collection.d.ts:--:--: The last overload is declared here. - ]); - - // Additional cases - const m1 = new Map([['num', 123], ['str', 'val1']]); - ~~~ -!!! error TS2769: No overload matches this call. -!!! error TS2769: The last overload gave the following error. -!!! error TS2769: Type 'number' is not assignable to type 'string'. -!!! related TS2771 lib.es2015.collection.d.ts:--:--: The last overload is declared here. - const m2 = new Map([['num', 456], ['str', 'val2']] as const); - ~~~~~~ -!!! error TS2769: No overload matches this call. -!!! error TS2769: The last overload gave the following error. -!!! error TS2769: Type '"val2"' is not assignable to type '456'. -!!! related TS2771 lib.es2015.collection.d.ts:--:--: The last overload is declared here. - const m3 = new Map([['num' as const, 456], ['str' as const, 'val2']]); - ~~~~~~ -!!! error TS2769: No overload matches this call. -!!! error TS2769: The last overload gave the following error. -!!! error TS2769: Type 'string' is not assignable to type 'number'. -!!! related TS2771 lib.es2015.collection.d.ts:--:--: The last overload is declared here. - \ No newline at end of file diff --git a/tsc/testdata/baselines/reference/conformance/new-Map1.types b/tsc/testdata/baselines/reference/conformance/new-Map1.types index eab380f1f2c97..dcc7d379b50ec 100644 --- a/tsc/testdata/baselines/reference/conformance/new-Map1.types +++ b/tsc/testdata/baselines/reference/conformance/new-Map1.types @@ -4,7 +4,7 @@ // https://github.com/microsoft/TypeScript/issues/37527#issuecomment-628802102 const sample: Map = new Map([[1, 1], ["yes", 1]]); >sample : Map ->new Map([[1, 1], ["yes", 1]]) : Map +>new Map([[1, 1], ["yes", 1]]) : Map >Map : MapConstructor >[[1, 1], ["yes", 1]] : ([string, number] | [number, number])[] >[1, 1] : [number, number] @@ -22,7 +22,7 @@ function test(_a: Map) {} test(new Map([["test" ,true] ,[1 ,false]])) >test(new Map([["test" ,true] ,[1 ,false]])) : void >test : (_a: Map) => void ->new Map([["test" ,true] ,[1 ,false]]) : Map +>new Map([["test" ,true] ,[1 ,false]]) : Map >Map : MapConstructor >[["test" ,true] ,[1 ,false]] : ([string, true] | [number, false])[] >["test" ,true] : [string, true] @@ -59,8 +59,8 @@ const M1 = new Map([ ]); const M2 = new Map([ ->M2 : Map ->new Map([ ...M1, ['k', {a: 1}],]) : Map +>M2 : Map +>new Map([ ...M1, ['k', {a: 1}],]) : Map >Map : MapConstructor >[ ...M1, ['k', {a: 1}],] : ([string, { a: number; b: string; }] | [string, { a: number; }])[] @@ -79,8 +79,8 @@ const M2 = new Map([ // Additional cases const m1 = new Map([['num', 123], ['str', 'val1']]); ->m1 : Map ->new Map([['num', 123], ['str', 'val1']]) : Map +>m1 : Map +>new Map([['num', 123], ['str', 'val1']]) : Map >Map : MapConstructor >[['num', 123], ['str', 'val1']] : ([string, string] | [string, number])[] >['num', 123] : [string, number] @@ -91,8 +91,8 @@ const m1 = new Map([['num', 123], ['str', 'val1']]); >'val1' : "val1" const m2 = new Map([['num', 456], ['str', 'val2']] as const); ->m2 : Map<"num" | "str", 456> ->new Map([['num', 456], ['str', 'val2']] as const) : Map<"num" | "str", 456> +>m2 : Map<"num" | "str", "val2" | 456> +>new Map([['num', 456], ['str', 'val2']] as const) : Map<"num" | "str", "val2" | 456> >Map : MapConstructor >[['num', 456], ['str', 'val2']] as const : readonly [readonly ["num", 456], readonly ["str", "val2"]] >[['num', 456], ['str', 'val2']] : readonly [readonly ["num", 456], readonly ["str", "val2"]] @@ -104,8 +104,8 @@ const m2 = new Map([['num', 456], ['str', 'val2']] as const); >'val2' : "val2" const m3 = new Map([['num' as const, 456], ['str' as const, 'val2']]); ->m3 : Map<"num" | "str", number> ->new Map([['num' as const, 456], ['str' as const, 'val2']]) : Map<"num" | "str", number> +>m3 : Map<"num" | "str", string | number> +>new Map([['num' as const, 456], ['str' as const, 'val2']]) : Map<"num" | "str", string | number> >Map : MapConstructor >[['num' as const, 456], ['str' as const, 'val2']] : (["num", number] | ["str", string])[] >['num' as const, 456] : ["num", number] From b53105ad8c9356c2562de64964a14c2171870fb3 Mon Sep 17 00:00:00 2001 From: Dave van Soest Date: Wed, 21 Oct 2026 17:01:06 +0200 Subject: [PATCH 3/7] fix: overload ordering of map constructor --- .../libs/lib.es2015.collection.temp.ts | 202 ++++++++++++++++++ 1 file changed, 202 insertions(+) create mode 100644 tsc/internal/bundled/libs/lib.es2015.collection.temp.ts diff --git a/tsc/internal/bundled/libs/lib.es2015.collection.temp.ts b/tsc/internal/bundled/libs/lib.es2015.collection.temp.ts new file mode 100644 index 0000000000000..0b8abc9ea71bd --- /dev/null +++ b/tsc/internal/bundled/libs/lib.es2015.collection.temp.ts @@ -0,0 +1,202 @@ +/*! ***************************************************************************** +Copyright (c) Microsoft Corporation. All rights reserved. +Licensed under the Apache License, Version 2.0 (the "License"); you may not use +this file except in compliance with the License. You may obtain a copy of the +License at http://www.apache.org/licenses/LICENSE-2.0 + +THIS CODE IS PROVIDED ON AN *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY IMPLIED +WARRANTIES OR CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE, +MERCHANTABILITY OR NON-INFRINGEMENT. + +See the Apache Version 2.0 License for specific language governing permissions +and limitations under the License. +***************************************************************************** */ + + +interface Map { + /** + * Removes all elements from the Map. + */ + clear(): void; + /** + * @returns true if an element in the Map existed and has been removed, or false if the element does not exist. + */ + delete(key: K): boolean; + /** + * Executes a provided function once per each key/value pair in the Map, in insertion order. + */ + forEach(callbackfn: (value: V, key: K, map: Map) => void, thisArg?: any): void; + /** + * Returns a specified element from the Map object. If the value that is associated to the provided key is an object, then you will get a reference to that object and any change made to that object will effectively modify it inside the Map. + * @returns Returns the element associated with the specified key. If no element is associated with the specified key, undefined is returned. + */ + get(key: K): V | undefined; + /** + * @returns boolean indicating whether an element with the specified key exists or not. + */ + has(key: K): boolean; + /** + * Adds a new element with a specified key and value to the Map. If an element with the same key already exists, the element will be updated. + */ + set(key: K, value: V): this; + /** + * @returns the number of elements in the Map. + */ + readonly size: number; +} + +interface MapConstructor { + new (): Map; + new (entries?: readonly (readonly [K, V])[] | null): Map; + new (entries?: KVEntries | null): Map; + readonly prototype: Map; +} +declare var Map: MapConstructor; + +export const x = new Map([]); + +// https://github.com/microsoft/TypeScript/issues/37527#issuecomment-628802102 +export const sample: Map = new Map([[1, 1], ["yes", 1]]); // errors + +// https://github.com/microsoft/TypeScript/issues/37527#issuecomment-750412755 +function test(_a: Map) {} +test(new Map([["test" ,true] ,[1 ,false]])) + +interface MapIterator extends IteratorObject { + [Symbol.iterator](): MapIterator; +} + +interface Map { + /** Returns an iterable of entries in the map. */ + [Symbol.iterator](): MapIterator<[K, V]>; + + /** + * Returns an iterable of key, value pairs for every entry in the map. + */ + entries(): MapIterator<[K, V]>; + + /** + * Returns an iterable of keys in the map + */ + keys(): MapIterator; + + /** + * Returns an iterable of values in the map + */ + values(): MapIterator; +} + +// https://github.com/microsoft/TypeScript/issues/33611#issue-498858215 +export const M1 = new Map([ ['k', {a: 1, b: 'asd'}], ['k', {a: 2, b: 'asd'}] ]); +export const M2 = new Map([ ...M1, ['k', {a: 1}] ]); + +// https://github.com/microsoft/TypeScript/blob/d61a7d235906e78be9b111de0ba060e28e67ecfa/tsc/testdata/tests/cases/compiler/inferFromGenericFunctionReturnTypes3.ts#L88 +export function objectToMap(obj: any) { + return new Map(Object.keys(obj).map(key => [key, obj[key]])); +}; + +interface ReadonlyMap { + forEach(callbackfn: (value: V, key: K, map: ReadonlyMap) => void, thisArg?: any): void; + get(key: K): V | undefined; + has(key: K): boolean; + readonly size: number; +} + +interface WeakMap { + /** + * Removes the specified element from the WeakMap. + * @returns true if the element was successfully removed, or false if it was not present. + */ + delete(key: K): boolean; + /** + * @returns a specified element. + */ + get(key: K): V | undefined; + /** + * @returns a boolean indicating whether an element with the specified key exists or not. + */ + has(key: K): boolean; + /** + * Adds a new element with a specified key and value. + * @param key Must be an object or symbol. + */ + set(key: K, value: V): this; +} + +interface WeakMapConstructor { + new (entries?: readonly (readonly [K, V])[] | null): WeakMap; + readonly prototype: WeakMap; +} +declare var WeakMap: WeakMapConstructor; + +interface Set { + /** + * Appends a new element with a specified value to the end of the Set. + */ + add(value: T): this; + /** + * Removes all elements from the Set. + */ + clear(): void; + /** + * Removes a specified value from the Set. + * @returns Returns true if an element in the Set existed and has been removed, or false if the element does not exist. + */ + delete(value: T): boolean; + /** + * Executes a provided function once per each value in the Set object, in insertion order. + */ + forEach(callbackfn: (value: T, value2: T, set: Set) => void, thisArg?: any): void; + /** + * @returns a boolean indicating whether an element with the specified value exists in the Set or not. + */ + has(value: T): boolean; + /** + * @returns the number of (unique) elements in the Set. + */ + readonly size: number; +} + +interface SetConstructor { + new (values?: readonly T[] | null): Set; + readonly prototype: Set; +} +declare var Set: SetConstructor; + +interface ReadonlySet { + /** + * Executes a provided function once per each value in the ReadonlySet object, in insertion order. + */ + forEach(callbackfn: (value: T, value2: T, set: ReadonlySet) => void, thisArg?: any): void; + /** + * @returns a boolean indicating whether an element with the specified value exists in the Set or not. + */ + has(value: T): boolean; + /** + * @returns the number of (unique) elements in the Set. + */ + readonly size: number; +} + +interface WeakSet { + /** + * Appends a new value to the end of the WeakSet. + */ + add(value: T): this; + /** + * Removes the specified element from the WeakSet. + * @returns Returns true if the element existed and has been removed, or false if the element does not exist. + */ + delete(value: T): boolean; + /** + * @returns a boolean indicating whether a value exists in the WeakSet or not. + */ + has(value: T): boolean; +} + +interface WeakSetConstructor { + new (values?: readonly T[] | null): WeakSet; + readonly prototype: WeakSet; +} +declare var WeakSet: WeakSetConstructor; From 6bd8d0d5f6936687326df38af7853c4da220f256 Mon Sep 17 00:00:00 2001 From: Dave van Soest Date: Wed, 21 Oct 2026 20:41:00 +0200 Subject: [PATCH 4/7] Delete scratch file tsc/internal/bundled/libs/lib.es2015.collection.temp.ts --- .../libs/lib.es2015.collection.temp.ts | 202 ------------------ 1 file changed, 202 deletions(-) delete mode 100644 tsc/internal/bundled/libs/lib.es2015.collection.temp.ts diff --git a/tsc/internal/bundled/libs/lib.es2015.collection.temp.ts b/tsc/internal/bundled/libs/lib.es2015.collection.temp.ts deleted file mode 100644 index 0b8abc9ea71bd..0000000000000 --- a/tsc/internal/bundled/libs/lib.es2015.collection.temp.ts +++ /dev/null @@ -1,202 +0,0 @@ -/*! ***************************************************************************** -Copyright (c) Microsoft Corporation. All rights reserved. -Licensed under the Apache License, Version 2.0 (the "License"); you may not use -this file except in compliance with the License. You may obtain a copy of the -License at http://www.apache.org/licenses/LICENSE-2.0 - -THIS CODE IS PROVIDED ON AN *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY IMPLIED -WARRANTIES OR CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE, -MERCHANTABILITY OR NON-INFRINGEMENT. - -See the Apache Version 2.0 License for specific language governing permissions -and limitations under the License. -***************************************************************************** */ - - -interface Map { - /** - * Removes all elements from the Map. - */ - clear(): void; - /** - * @returns true if an element in the Map existed and has been removed, or false if the element does not exist. - */ - delete(key: K): boolean; - /** - * Executes a provided function once per each key/value pair in the Map, in insertion order. - */ - forEach(callbackfn: (value: V, key: K, map: Map) => void, thisArg?: any): void; - /** - * Returns a specified element from the Map object. If the value that is associated to the provided key is an object, then you will get a reference to that object and any change made to that object will effectively modify it inside the Map. - * @returns Returns the element associated with the specified key. If no element is associated with the specified key, undefined is returned. - */ - get(key: K): V | undefined; - /** - * @returns boolean indicating whether an element with the specified key exists or not. - */ - has(key: K): boolean; - /** - * Adds a new element with a specified key and value to the Map. If an element with the same key already exists, the element will be updated. - */ - set(key: K, value: V): this; - /** - * @returns the number of elements in the Map. - */ - readonly size: number; -} - -interface MapConstructor { - new (): Map; - new (entries?: readonly (readonly [K, V])[] | null): Map; - new (entries?: KVEntries | null): Map; - readonly prototype: Map; -} -declare var Map: MapConstructor; - -export const x = new Map([]); - -// https://github.com/microsoft/TypeScript/issues/37527#issuecomment-628802102 -export const sample: Map = new Map([[1, 1], ["yes", 1]]); // errors - -// https://github.com/microsoft/TypeScript/issues/37527#issuecomment-750412755 -function test(_a: Map) {} -test(new Map([["test" ,true] ,[1 ,false]])) - -interface MapIterator extends IteratorObject { - [Symbol.iterator](): MapIterator; -} - -interface Map { - /** Returns an iterable of entries in the map. */ - [Symbol.iterator](): MapIterator<[K, V]>; - - /** - * Returns an iterable of key, value pairs for every entry in the map. - */ - entries(): MapIterator<[K, V]>; - - /** - * Returns an iterable of keys in the map - */ - keys(): MapIterator; - - /** - * Returns an iterable of values in the map - */ - values(): MapIterator; -} - -// https://github.com/microsoft/TypeScript/issues/33611#issue-498858215 -export const M1 = new Map([ ['k', {a: 1, b: 'asd'}], ['k', {a: 2, b: 'asd'}] ]); -export const M2 = new Map([ ...M1, ['k', {a: 1}] ]); - -// https://github.com/microsoft/TypeScript/blob/d61a7d235906e78be9b111de0ba060e28e67ecfa/tsc/testdata/tests/cases/compiler/inferFromGenericFunctionReturnTypes3.ts#L88 -export function objectToMap(obj: any) { - return new Map(Object.keys(obj).map(key => [key, obj[key]])); -}; - -interface ReadonlyMap { - forEach(callbackfn: (value: V, key: K, map: ReadonlyMap) => void, thisArg?: any): void; - get(key: K): V | undefined; - has(key: K): boolean; - readonly size: number; -} - -interface WeakMap { - /** - * Removes the specified element from the WeakMap. - * @returns true if the element was successfully removed, or false if it was not present. - */ - delete(key: K): boolean; - /** - * @returns a specified element. - */ - get(key: K): V | undefined; - /** - * @returns a boolean indicating whether an element with the specified key exists or not. - */ - has(key: K): boolean; - /** - * Adds a new element with a specified key and value. - * @param key Must be an object or symbol. - */ - set(key: K, value: V): this; -} - -interface WeakMapConstructor { - new (entries?: readonly (readonly [K, V])[] | null): WeakMap; - readonly prototype: WeakMap; -} -declare var WeakMap: WeakMapConstructor; - -interface Set { - /** - * Appends a new element with a specified value to the end of the Set. - */ - add(value: T): this; - /** - * Removes all elements from the Set. - */ - clear(): void; - /** - * Removes a specified value from the Set. - * @returns Returns true if an element in the Set existed and has been removed, or false if the element does not exist. - */ - delete(value: T): boolean; - /** - * Executes a provided function once per each value in the Set object, in insertion order. - */ - forEach(callbackfn: (value: T, value2: T, set: Set) => void, thisArg?: any): void; - /** - * @returns a boolean indicating whether an element with the specified value exists in the Set or not. - */ - has(value: T): boolean; - /** - * @returns the number of (unique) elements in the Set. - */ - readonly size: number; -} - -interface SetConstructor { - new (values?: readonly T[] | null): Set; - readonly prototype: Set; -} -declare var Set: SetConstructor; - -interface ReadonlySet { - /** - * Executes a provided function once per each value in the ReadonlySet object, in insertion order. - */ - forEach(callbackfn: (value: T, value2: T, set: ReadonlySet) => void, thisArg?: any): void; - /** - * @returns a boolean indicating whether an element with the specified value exists in the Set or not. - */ - has(value: T): boolean; - /** - * @returns the number of (unique) elements in the Set. - */ - readonly size: number; -} - -interface WeakSet { - /** - * Appends a new value to the end of the WeakSet. - */ - add(value: T): this; - /** - * Removes the specified element from the WeakSet. - * @returns Returns true if the element existed and has been removed, or false if the element does not exist. - */ - delete(value: T): boolean; - /** - * @returns a boolean indicating whether a value exists in the WeakSet or not. - */ - has(value: T): boolean; -} - -interface WeakSetConstructor { - new (values?: readonly T[] | null): WeakSet; - readonly prototype: WeakSet; -} -declare var WeakSet: WeakSetConstructor; From b79a9299628eb8c1d8c626d22fbfde379a5565d5 Mon Sep 17 00:00:00 2001 From: Dave van Soest Date: Thu, 22 Oct 2026 19:00:54 +0200 Subject: [PATCH 5/7] Align map construction type inference between collection and iterable libs. --- .../bundled/libs/lib.es2015.iterable.d.ts | 1 + .../reference/conformance/new-Map2.errors.txt | 17 +++++++++++ .../reference/conformance/new-Map2.js | 19 ++++++++++++ .../reference/conformance/new-Map2.symbols | 23 +++++++++++++++ .../reference/conformance/new-Map2.types | 29 +++++++++++++++++++ .../es6/mapConstruction/new-Map2.ts | 7 +++++ 6 files changed, 96 insertions(+) create mode 100644 tsc/testdata/baselines/reference/conformance/new-Map2.errors.txt create mode 100644 tsc/testdata/baselines/reference/conformance/new-Map2.js create mode 100644 tsc/testdata/baselines/reference/conformance/new-Map2.symbols create mode 100644 tsc/testdata/baselines/reference/conformance/new-Map2.types create mode 100644 tsc/testdata/tests/cases/conformance/es6/mapConstruction/new-Map2.ts diff --git a/tsc/internal/bundled/libs/lib.es2015.iterable.d.ts b/tsc/internal/bundled/libs/lib.es2015.iterable.d.ts index 7396a53feb8cf..650139576ddac 100644 --- a/tsc/internal/bundled/libs/lib.es2015.iterable.d.ts +++ b/tsc/internal/bundled/libs/lib.es2015.iterable.d.ts @@ -179,6 +179,7 @@ interface ReadonlyMap { interface MapConstructor { new (): Map; new (iterable?: Iterable | null): Map; + new (iterable?: Iterable | null): Map; } interface WeakMap {} diff --git a/tsc/testdata/baselines/reference/conformance/new-Map2.errors.txt b/tsc/testdata/baselines/reference/conformance/new-Map2.errors.txt new file mode 100644 index 0000000000000..54a1fa3dea806 --- /dev/null +++ b/tsc/testdata/baselines/reference/conformance/new-Map2.errors.txt @@ -0,0 +1,17 @@ +new-Map2.ts(6,7): error TS7034: Variable 'a3' implicitly has type 'any[]' in some locations where its type cannot be determined. +new-Map2.ts(7,20): error TS7005: Variable 'a3' implicitly has an 'any[]' type. + + +==== new-Map2.ts (2 errors) ==== + const m1 = new Map([]); + + const a2: any[] = []; + const m2 = new Map(a2); + + const a3 = []; + ~~ +!!! error TS7034: Variable 'a3' implicitly has type 'any[]' in some locations where its type cannot be determined. + const m3 = new Map(a3); + ~~ +!!! error TS7005: Variable 'a3' implicitly has an 'any[]' type. + \ No newline at end of file diff --git a/tsc/testdata/baselines/reference/conformance/new-Map2.js b/tsc/testdata/baselines/reference/conformance/new-Map2.js new file mode 100644 index 0000000000000..3139f2d165031 --- /dev/null +++ b/tsc/testdata/baselines/reference/conformance/new-Map2.js @@ -0,0 +1,19 @@ +//// [tests/cases/conformance/es6/mapConstruction/new-Map2.ts] //// + +//// [new-Map2.ts] +const m1 = new Map([]); + +const a2: any[] = []; +const m2 = new Map(a2); + +const a3 = []; +const m3 = new Map(a3); + + +//// [new-Map2.js] +"use strict"; +const m1 = new Map([]); +const a2 = []; +const m2 = new Map(a2); +const a3 = []; +const m3 = new Map(a3); diff --git a/tsc/testdata/baselines/reference/conformance/new-Map2.symbols b/tsc/testdata/baselines/reference/conformance/new-Map2.symbols new file mode 100644 index 0000000000000..2a082d8006ee6 --- /dev/null +++ b/tsc/testdata/baselines/reference/conformance/new-Map2.symbols @@ -0,0 +1,23 @@ +//// [tests/cases/conformance/es6/mapConstruction/new-Map2.ts] //// + +=== new-Map2.ts === +const m1 = new Map([]); +>m1 : Symbol(m1, Decl(new-Map2.ts, 0, 5)) +>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, --, --), Decl(lib.es2026.collection.d.ts, --, --)) + +const a2: any[] = []; +>a2 : Symbol(a2, Decl(new-Map2.ts, 2, 5)) + +const m2 = new Map(a2); +>m2 : Symbol(m2, Decl(new-Map2.ts, 3, 5)) +>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, --, --), Decl(lib.es2026.collection.d.ts, --, --)) +>a2 : Symbol(a2, Decl(new-Map2.ts, 2, 5)) + +const a3 = []; +>a3 : Symbol(a3, Decl(new-Map2.ts, 5, 5)) + +const m3 = new Map(a3); +>m3 : Symbol(m3, Decl(new-Map2.ts, 6, 5)) +>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, --, --), Decl(lib.es2026.collection.d.ts, --, --)) +>a3 : Symbol(a3, Decl(new-Map2.ts, 5, 5)) + diff --git a/tsc/testdata/baselines/reference/conformance/new-Map2.types b/tsc/testdata/baselines/reference/conformance/new-Map2.types new file mode 100644 index 0000000000000..81aad9abbe2c7 --- /dev/null +++ b/tsc/testdata/baselines/reference/conformance/new-Map2.types @@ -0,0 +1,29 @@ +//// [tests/cases/conformance/es6/mapConstruction/new-Map2.ts] //// + +=== new-Map2.ts === +const m1 = new Map([]); +>m1 : Map +>new Map([]) : Map +>Map : MapConstructor +>[] : never[] + +const a2: any[] = []; +>a2 : any[] +>[] : never[] + +const m2 = new Map(a2); +>m2 : Map +>new Map(a2) : Map +>Map : MapConstructor +>a2 : any[] + +const a3 = []; +>a3 : any[] +>[] : never[] + +const m3 = new Map(a3); +>m3 : Map +>new Map(a3) : Map +>Map : MapConstructor +>a3 : any[] + diff --git a/tsc/testdata/tests/cases/conformance/es6/mapConstruction/new-Map2.ts b/tsc/testdata/tests/cases/conformance/es6/mapConstruction/new-Map2.ts new file mode 100644 index 0000000000000..1a07769dd67ce --- /dev/null +++ b/tsc/testdata/tests/cases/conformance/es6/mapConstruction/new-Map2.ts @@ -0,0 +1,7 @@ +const m1 = new Map([]); + +const a2: any[] = []; +const m2 = new Map(a2); + +const a3 = []; +const m3 = new Map(a3); From 88d81738b2b5faeef8afd1568a8182ef229bcc9f Mon Sep 17 00:00:00 2001 From: Dave van Soest Date: Thu, 22 Oct 2026 19:52:33 +0200 Subject: [PATCH 6/7] Fix correct order of Map constructor overloads in collection lib. --- tsc/internal/bundled/libs/lib.es2015.collection.d.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tsc/internal/bundled/libs/lib.es2015.collection.d.ts b/tsc/internal/bundled/libs/lib.es2015.collection.d.ts index 1bd13d6cd4539..e5aced2741bd7 100644 --- a/tsc/internal/bundled/libs/lib.es2015.collection.d.ts +++ b/tsc/internal/bundled/libs/lib.es2015.collection.d.ts @@ -48,8 +48,8 @@ interface Map { interface MapConstructor { new (): Map; - new (entries?: KVEntries | null): Map; new (entries?: readonly (readonly [K, V])[] | null): Map; + new (entries?: KVEntries | null): Map; readonly prototype: Map; } declare var Map: MapConstructor; From 9745901f37771cc21606256fd9c7116cc9154fee Mon Sep 17 00:00:00 2001 From: Dave van Soest Date: Thu, 22 Oct 2026 20:20:12 +0200 Subject: [PATCH 7/7] Reduce collection lib generic constraint to element only to equal iterable lib. --- tsc/internal/bundled/libs/lib.es2015.collection.d.ts | 2 +- tsc/testdata/baselines/reference/compiler/newMap.errors.txt | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/tsc/internal/bundled/libs/lib.es2015.collection.d.ts b/tsc/internal/bundled/libs/lib.es2015.collection.d.ts index e5aced2741bd7..55399ad8ec1f1 100644 --- a/tsc/internal/bundled/libs/lib.es2015.collection.d.ts +++ b/tsc/internal/bundled/libs/lib.es2015.collection.d.ts @@ -49,7 +49,7 @@ interface Map { interface MapConstructor { new (): Map; new (entries?: readonly (readonly [K, V])[] | null): Map; - new (entries?: KVEntries | null): Map; + new (entries?: readonly KV[] | null): Map; readonly prototype: Map; } declare var Map: MapConstructor; diff --git a/tsc/testdata/baselines/reference/compiler/newMap.errors.txt b/tsc/testdata/baselines/reference/compiler/newMap.errors.txt index 8bb425f911762..ec31222ec6a3e 100644 --- a/tsc/testdata/baselines/reference/compiler/newMap.errors.txt +++ b/tsc/testdata/baselines/reference/compiler/newMap.errors.txt @@ -1,9 +1,9 @@ -newMap.ts(1,9): error TS2344: Type 'string' does not satisfy the constraint 'readonly (readonly [any, any])[]'. +newMap.ts(1,9): error TS2344: Type 'string' does not satisfy the constraint 'readonly [any, any]'. ==== newMap.ts (1 errors) ==== new Map(); ~~~~~~ -!!! error TS2344: Type 'string' does not satisfy the constraint 'readonly (readonly [any, any])[]'. +!!! error TS2344: Type 'string' does not satisfy the constraint 'readonly [any, any]'. new WeakMap(); \ No newline at end of file