Propagate wildcard types in non-homomorphic mapped types (#41622)

* Propagate wildcard types in non-homomorphic mapped types

* Add regression test

* Accept new baselines

* Accept new baselines
This commit is contained in:
Anders Hejlsberg
2020-12-01 13:57:00 -08:00
committed by GitHub
parent d57954345b
commit 4782c74b75
8 changed files with 71 additions and 7 deletions

View File

@@ -15276,7 +15276,9 @@ namespace ts {
});
}
}
return instantiateAnonymousType(type, mapper);
// If the constraint type of the instantiation is the wildcard type, return the wildcard type.
const result = <MappedType>instantiateAnonymousType(type, mapper);
return getConstraintTypeFromMappedType(result) === wildcardType ? wildcardType : result;
}
function getModifiedReadonlyState(state: boolean, modifiers: MappedTypeModifiers) {

View File

@@ -326,4 +326,10 @@ tests/cases/conformance/types/conditional/conditionalTypes2.ts(75,12): error TS2
declare function gg<T>(f: (x: Foo3<T>) => void): void;
type Foo3<T> = T extends number ? { n: T } : { x: T };
gg(ff);
// Repro from #41613
type Wat<K extends string> = { x: { y: 0, z: 1 } } extends { x: { [P in K]: 0 } } ? true : false;
type Huh = Wat<"y">; // true

View File

@@ -237,6 +237,12 @@ declare function ff(x: Foo3<string>): void;
declare function gg<T>(f: (x: Foo3<T>) => void): void;
type Foo3<T> = T extends number ? { n: T } : { x: T };
gg(ff);
// Repro from #41613
type Wat<K extends string> = { 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> = T extends number ? {
} : {
x: T;
};
declare type Wat<K extends string> = {
x: {
y: 0;
z: 1;
};
} extends {
x: {
[P in K]: 0;
};
} ? true : false;
declare type Huh = Wat<"y">;

View File

@@ -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<K extends string> = { 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))

View File

@@ -527,3 +527,17 @@ gg(ff);
>gg : <T>(f: (x: Foo3<T>) => void) => void
>ff : (x: { x: string; }) => void
// Repro from #41613
type Wat<K extends string> = { x: { y: 0, z: 1 } } extends { x: { [P in K]: 0 } } ? true : false;
>Wat : Wat<K>
>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

View File

@@ -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<T> = { [P in NonOptionalKeys<T>]: 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<ListWidget>;
~~~~~~
!!! 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<ListWidget>
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; }'.

View File

@@ -119,7 +119,7 @@ export interface ListWidget {
>"collapsable" : boolean
"each": Child<ListWidget>;
>"each" : Child<ListWidget>
>"each" : any
}
type ListChild = Child<ListWidget>

View File

@@ -239,3 +239,9 @@ declare function ff(x: Foo3<string>): void;
declare function gg<T>(f: (x: Foo3<T>) => void): void;
type Foo3<T> = T extends number ? { n: T } : { x: T };
gg(ff);
// Repro from #41613
type Wat<K extends string> = { x: { y: 0, z: 1 } } extends { x: { [P in K]: 0 } } ? true : false;
type Huh = Wat<"y">; // true