From 033ed586e60c4c76e0c61fdb592215b38ac332a0 Mon Sep 17 00:00:00 2001 From: Anders Hejlsberg Date: Fri, 20 Nov 2020 17:31:14 -0800 Subject: [PATCH 1/4] Propagate wildcard types in non-homomorphic mapped types --- src/compiler/checker.ts | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 9fc854515ee96..5d9cc4b31d41c 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -15269,7 +15269,9 @@ namespace ts { }); } } - return instantiateAnonymousType(type, mapper); + // If the constraint type of the instantiation is the wildcard type, return the wildcard type. + const result = instantiateAnonymousType(type, mapper); + return getConstraintTypeFromMappedType(result) === wildcardType ? wildcardType : result; } function getModifiedReadonlyState(state: boolean, modifiers: MappedTypeModifiers) { From f4d14eff5703ac9ebcd2c21caea3368af0eeeeb6 Mon Sep 17 00:00:00 2001 From: Anders Hejlsberg Date: Fri, 20 Nov 2020 17:37:02 -0800 Subject: [PATCH 2/4] Add regression test --- .../conformance/types/conditional/conditionalTypes2.ts | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/tests/cases/conformance/types/conditional/conditionalTypes2.ts b/tests/cases/conformance/types/conditional/conditionalTypes2.ts index ea30ec89fbfa8..a2397296ee678 100644 --- a/tests/cases/conformance/types/conditional/conditionalTypes2.ts +++ b/tests/cases/conformance/types/conditional/conditionalTypes2.ts @@ -239,3 +239,9 @@ declare function ff(x: Foo3): void; declare function gg(f: (x: Foo3) => void): void; type Foo3 = T extends number ? { n: T } : { x: T }; gg(ff); + +// Repro from #41613 + +type Wat = { x: { y: 0, z: 1 } } extends { x: { [P in K]: 0 } } ? true : false; + +type Huh = Wat<"y">; // true From eb489ccdfb5ff60771d490bea755c3cc86ca98ed Mon Sep 17 00:00:00 2001 From: Anders Hejlsberg Date: Fri, 20 Nov 2020 17:37:10 -0800 Subject: [PATCH 3/4] Accept new baselines --- .../reference/conditionalTypes2.errors.txt | 6 ++++++ tests/baselines/reference/conditionalTypes2.js | 17 +++++++++++++++++ .../reference/conditionalTypes2.symbols | 16 ++++++++++++++++ .../baselines/reference/conditionalTypes2.types | 14 ++++++++++++++ 4 files changed, 53 insertions(+) diff --git a/tests/baselines/reference/conditionalTypes2.errors.txt b/tests/baselines/reference/conditionalTypes2.errors.txt index 1f92090e2e137..9eaf6ae95293b 100644 --- a/tests/baselines/reference/conditionalTypes2.errors.txt +++ b/tests/baselines/reference/conditionalTypes2.errors.txt @@ -326,4 +326,10 @@ tests/cases/conformance/types/conditional/conditionalTypes2.ts(75,12): error TS2 declare function gg(f: (x: Foo3) => void): void; type Foo3 = T extends number ? { n: T } : { x: T }; gg(ff); + + // Repro from #41613 + + type Wat = { x: { y: 0, z: 1 } } extends { x: { [P in K]: 0 } } ? true : false; + + type Huh = Wat<"y">; // true \ No newline at end of file diff --git a/tests/baselines/reference/conditionalTypes2.js b/tests/baselines/reference/conditionalTypes2.js index ac2cb7465f72d..f775bf0564b03 100644 --- a/tests/baselines/reference/conditionalTypes2.js +++ b/tests/baselines/reference/conditionalTypes2.js @@ -237,6 +237,12 @@ declare function ff(x: Foo3): void; declare function gg(f: (x: Foo3) => void): void; type Foo3 = T extends number ? { n: T } : { x: T }; gg(ff); + +// Repro from #41613 + +type Wat = { x: { y: 0, z: 1 } } extends { x: { [P in K]: 0 } } ? true : false; + +type Huh = Wat<"y">; // true //// [conditionalTypes2.js] @@ -477,3 +483,14 @@ declare type Foo3 = T extends number ? { } : { x: T; }; +declare type Wat = { + x: { + y: 0; + z: 1; + }; +} extends { + x: { + [P in K]: 0; + }; +} ? true : false; +declare type Huh = Wat<"y">; diff --git a/tests/baselines/reference/conditionalTypes2.symbols b/tests/baselines/reference/conditionalTypes2.symbols index 9f980b3d0cec3..b085d8b255ea5 100644 --- a/tests/baselines/reference/conditionalTypes2.symbols +++ b/tests/baselines/reference/conditionalTypes2.symbols @@ -841,3 +841,19 @@ gg(ff); >gg : Symbol(gg, Decl(conditionalTypes2.ts, 234, 43)) >ff : Symbol(ff, Decl(conditionalTypes2.ts, 230, 2)) +// Repro from #41613 + +type Wat = { x: { y: 0, z: 1 } } extends { x: { [P in K]: 0 } } ? true : false; +>Wat : Symbol(Wat, Decl(conditionalTypes2.ts, 237, 7)) +>K : Symbol(K, Decl(conditionalTypes2.ts, 241, 9)) +>x : Symbol(x, Decl(conditionalTypes2.ts, 241, 30)) +>y : Symbol(y, Decl(conditionalTypes2.ts, 241, 35)) +>z : Symbol(z, Decl(conditionalTypes2.ts, 241, 41)) +>x : Symbol(x, Decl(conditionalTypes2.ts, 241, 60)) +>P : Symbol(P, Decl(conditionalTypes2.ts, 241, 67)) +>K : Symbol(K, Decl(conditionalTypes2.ts, 241, 9)) + +type Huh = Wat<"y">; // true +>Huh : Symbol(Huh, Decl(conditionalTypes2.ts, 241, 97)) +>Wat : Symbol(Wat, Decl(conditionalTypes2.ts, 237, 7)) + diff --git a/tests/baselines/reference/conditionalTypes2.types b/tests/baselines/reference/conditionalTypes2.types index d7487a1111007..b74025500a46b 100644 --- a/tests/baselines/reference/conditionalTypes2.types +++ b/tests/baselines/reference/conditionalTypes2.types @@ -527,3 +527,17 @@ gg(ff); >gg : (f: (x: Foo3) => void) => void >ff : (x: { x: string; }) => void +// Repro from #41613 + +type Wat = { x: { y: 0, z: 1 } } extends { x: { [P in K]: 0 } } ? true : false; +>Wat : Wat +>x : { y: 0; z: 1; } +>y : 0 +>z : 1 +>x : { [P in K]: 0; } +>true : true +>false : false + +type Huh = Wat<"y">; // true +>Huh : true + From 7083ad4cb1cd19b812afeb51784169d76179a143 Mon Sep 17 00:00:00 2001 From: Anders Hejlsberg Date: Fri, 20 Nov 2020 18:25:10 -0800 Subject: [PATCH 4/4] Accept new baselines --- .../reference/recursiveMappedTypes.errors.txt | 13 ++++++++----- .../baselines/reference/recursiveMappedTypes.types | 2 +- 2 files changed, 9 insertions(+), 6 deletions(-) diff --git a/tests/baselines/reference/recursiveMappedTypes.errors.txt b/tests/baselines/reference/recursiveMappedTypes.errors.txt index ee8b0b02ddb84..56a9d1c02140f 100644 --- a/tests/baselines/reference/recursiveMappedTypes.errors.txt +++ b/tests/baselines/reference/recursiveMappedTypes.errors.txt @@ -6,10 +6,11 @@ tests/cases/conformance/types/mapped/recursiveMappedTypes.ts(11,6): error TS2456 tests/cases/conformance/types/mapped/recursiveMappedTypes.ts(12,11): error TS2313: Type parameter 'K' has a circular constraint. tests/cases/conformance/types/mapped/recursiveMappedTypes.ts(20,19): error TS2589: Type instantiation is excessively deep and possibly infinite. tests/cases/conformance/types/mapped/recursiveMappedTypes.ts(66,25): error TS2313: Type parameter 'P' has a circular constraint. -tests/cases/conformance/types/mapped/recursiveMappedTypes.ts(79,1): error TS2615: Type of property '"each"' circularly references itself in mapped type '{ type: never; minimum_count: never; maximum_count: never; collapsable?: never; each: never; }'. +tests/cases/conformance/types/mapped/recursiveMappedTypes.ts(73,5): error TS2502: '"each"' is referenced directly or indirectly in its own type annotation. +tests/cases/conformance/types/mapped/recursiveMappedTypes.ts(73,13): error TS2615: Type of property '"each"' circularly references itself in mapped type '{ [P in keyof ListWidget]: undefined extends ListWidget[P] ? never : P; }'. -==== tests/cases/conformance/types/mapped/recursiveMappedTypes.ts (9 errors) ==== +==== tests/cases/conformance/types/mapped/recursiveMappedTypes.ts (10 errors) ==== // Recursive mapped types simply appear empty type Recurse = { @@ -93,7 +94,7 @@ tests/cases/conformance/types/mapped/recursiveMappedTypes.ts(79,1): error TS2615 type Child = { [P in NonOptionalKeys]: T[P] } ~~~~~~~~~~~~~~~~~~ !!! error TS2313: Type parameter 'P' has a circular constraint. -!!! related TS2751 tests/cases/conformance/types/mapped/recursiveMappedTypes.ts:79:1: Circularity originates in type at this location. +!!! related TS2751 tests/cases/conformance/types/mapped/recursiveMappedTypes.ts:73:13: Circularity originates in type at this location. export interface ListWidget { "type": "list", @@ -101,12 +102,14 @@ tests/cases/conformance/types/mapped/recursiveMappedTypes.ts(79,1): error TS2615 "maximum_count": number, "collapsable"?: boolean, //default to false, means all expanded "each": Child; + ~~~~~~ +!!! error TS2502: '"each"' is referenced directly or indirectly in its own type annotation. + ~~~~~~~~~~~~~~~~~ +!!! error TS2615: Type of property '"each"' circularly references itself in mapped type '{ [P in keyof ListWidget]: undefined extends ListWidget[P] ? never : P; }'. } type ListChild = Child declare let x: ListChild; x.type; - ~~~~~~ -!!! error TS2615: Type of property '"each"' circularly references itself in mapped type '{ type: never; minimum_count: never; maximum_count: never; collapsable?: never; each: never; }'. \ No newline at end of file diff --git a/tests/baselines/reference/recursiveMappedTypes.types b/tests/baselines/reference/recursiveMappedTypes.types index 3d317f688bfba..a3ebe7e60c068 100644 --- a/tests/baselines/reference/recursiveMappedTypes.types +++ b/tests/baselines/reference/recursiveMappedTypes.types @@ -119,7 +119,7 @@ export interface ListWidget { >"collapsable" : boolean "each": Child; ->"each" : Child +>"each" : any } type ListChild = Child