mirror of
https://github.com/microsoft/TypeScript.git
synced 2026-05-15 12:51:30 -05:00
Fix non-homomorphic mapped type constraint issues (#41807)
* Less aggressive wildcard check, 'keyof any' constraint for 'infer T' in mapped type constraint position * Accept new baselines * Add regression tests
This commit is contained in:
@@ -12081,6 +12081,11 @@ namespace ts {
|
||||
else if (grandParent.kind === SyntaxKind.TemplateLiteralTypeSpan) {
|
||||
inferences = append(inferences, stringType);
|
||||
}
|
||||
// When an 'infer T' declaration is in the constraint position of a mapped type, we infer a 'keyof any'
|
||||
// constraint.
|
||||
else if (grandParent.kind === SyntaxKind.TypeParameter && grandParent.parent.kind === SyntaxKind.MappedType) {
|
||||
inferences = append(inferences, keyofConstraintType);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -15281,8 +15286,7 @@ namespace ts {
|
||||
}
|
||||
}
|
||||
// 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;
|
||||
return instantiateType(getConstraintTypeFromMappedType(type), mapper) === wildcardType ? wildcardType : instantiateAnonymousType(type, mapper);
|
||||
}
|
||||
|
||||
function getModifiedReadonlyState(state: boolean, modifiers: MappedTypeModifiers) {
|
||||
|
||||
@@ -5,12 +5,11 @@ tests/cases/conformance/types/mapped/recursiveMappedTypes.ts(8,11): error TS2313
|
||||
tests/cases/conformance/types/mapped/recursiveMappedTypes.ts(11,6): error TS2456: Type alias 'Recurse2' circularly references itself.
|
||||
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(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 (10 errors) ====
|
||||
==== tests/cases/conformance/types/mapped/recursiveMappedTypes.ts (9 errors) ====
|
||||
// Recursive mapped types simply appear empty
|
||||
|
||||
type Recurse = {
|
||||
@@ -92,9 +91,6 @@ tests/cases/conformance/types/mapped/recursiveMappedTypes.ts(73,13): error TS261
|
||||
|
||||
type NonOptionalKeys<T> = { [P in keyof T]: undefined extends T[P] ? never : P }[keyof T];
|
||||
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:73:13: Circularity originates in type at this location.
|
||||
|
||||
export interface ListWidget {
|
||||
"type": "list",
|
||||
@@ -112,4 +108,16 @@ tests/cases/conformance/types/mapped/recursiveMappedTypes.ts(73,13): error TS261
|
||||
|
||||
declare let x: ListChild;
|
||||
x.type;
|
||||
|
||||
// Repros from #41790
|
||||
|
||||
export type TV<T, K extends keyof T> = T[K] extends Record<infer E, any> ? E : never;
|
||||
|
||||
export type ObjectOrArray<T, K extends keyof any = keyof any> = T[] | Record<K, T | Record<K, T> | T[]>;
|
||||
export type ThemeValue<K extends keyof ThemeType, ThemeType, TVal = any> =
|
||||
ThemeType[K] extends TVal[] ? number :
|
||||
ThemeType[K] extends Record<infer E, TVal> ? E :
|
||||
ThemeType[K] extends ObjectOrArray<infer F> ? F : never;
|
||||
|
||||
export type Foo<T> = T extends { [P in infer E]: any } ? E : never;
|
||||
|
||||
@@ -78,6 +78,18 @@ type ListChild = Child<ListWidget>
|
||||
|
||||
declare let x: ListChild;
|
||||
x.type;
|
||||
|
||||
// Repros from #41790
|
||||
|
||||
export type TV<T, K extends keyof T> = T[K] extends Record<infer E, any> ? E : never;
|
||||
|
||||
export type ObjectOrArray<T, K extends keyof any = keyof any> = T[] | Record<K, T | Record<K, T> | T[]>;
|
||||
export type ThemeValue<K extends keyof ThemeType, ThemeType, TVal = any> =
|
||||
ThemeType[K] extends TVal[] ? number :
|
||||
ThemeType[K] extends Record<infer E, TVal> ? E :
|
||||
ThemeType[K] extends ObjectOrArray<infer F> ? F : never;
|
||||
|
||||
export type Foo<T> = T extends { [P in infer E]: any } ? E : never;
|
||||
|
||||
|
||||
//// [recursiveMappedTypes.js]
|
||||
@@ -108,4 +120,10 @@ export interface ListWidget {
|
||||
"collapsable"?: boolean;
|
||||
"each": Child<ListWidget>;
|
||||
}
|
||||
export declare type TV<T, K extends keyof T> = T[K] extends Record<infer E, any> ? E : never;
|
||||
export declare type ObjectOrArray<T, K extends keyof any = keyof any> = T[] | Record<K, T | Record<K, T> | T[]>;
|
||||
export declare type ThemeValue<K extends keyof ThemeType, ThemeType, TVal = any> = ThemeType[K] extends TVal[] ? number : ThemeType[K] extends Record<infer E, TVal> ? E : ThemeType[K] extends ObjectOrArray<infer F> ? F : never;
|
||||
export declare type Foo<T> = T extends {
|
||||
[P in infer E]: any;
|
||||
} ? E : never;
|
||||
export {};
|
||||
|
||||
@@ -219,3 +219,64 @@ declare let x: ListChild;
|
||||
x.type;
|
||||
>x : Symbol(x, Decl(recursiveMappedTypes.ts, 77, 11))
|
||||
|
||||
// Repros from #41790
|
||||
|
||||
export type TV<T, K extends keyof T> = T[K] extends Record<infer E, any> ? E : never;
|
||||
>TV : Symbol(TV, Decl(recursiveMappedTypes.ts, 78, 7))
|
||||
>T : Symbol(T, Decl(recursiveMappedTypes.ts, 82, 15))
|
||||
>K : Symbol(K, Decl(recursiveMappedTypes.ts, 82, 17))
|
||||
>T : Symbol(T, Decl(recursiveMappedTypes.ts, 82, 15))
|
||||
>T : Symbol(T, Decl(recursiveMappedTypes.ts, 82, 15))
|
||||
>K : Symbol(K, Decl(recursiveMappedTypes.ts, 82, 17))
|
||||
>Record : Symbol(Record, Decl(lib.es5.d.ts, --, --))
|
||||
>E : Symbol(E, Decl(recursiveMappedTypes.ts, 82, 64))
|
||||
>E : Symbol(E, Decl(recursiveMappedTypes.ts, 82, 64))
|
||||
|
||||
export type ObjectOrArray<T, K extends keyof any = keyof any> = T[] | Record<K, T | Record<K, T> | T[]>;
|
||||
>ObjectOrArray : Symbol(ObjectOrArray, Decl(recursiveMappedTypes.ts, 82, 85))
|
||||
>T : Symbol(T, Decl(recursiveMappedTypes.ts, 84, 26))
|
||||
>K : Symbol(K, Decl(recursiveMappedTypes.ts, 84, 28))
|
||||
>T : Symbol(T, Decl(recursiveMappedTypes.ts, 84, 26))
|
||||
>Record : Symbol(Record, Decl(lib.es5.d.ts, --, --))
|
||||
>K : Symbol(K, Decl(recursiveMappedTypes.ts, 84, 28))
|
||||
>T : Symbol(T, Decl(recursiveMappedTypes.ts, 84, 26))
|
||||
>Record : Symbol(Record, Decl(lib.es5.d.ts, --, --))
|
||||
>K : Symbol(K, Decl(recursiveMappedTypes.ts, 84, 28))
|
||||
>T : Symbol(T, Decl(recursiveMappedTypes.ts, 84, 26))
|
||||
>T : Symbol(T, Decl(recursiveMappedTypes.ts, 84, 26))
|
||||
|
||||
export type ThemeValue<K extends keyof ThemeType, ThemeType, TVal = any> =
|
||||
>ThemeValue : Symbol(ThemeValue, Decl(recursiveMappedTypes.ts, 84, 104))
|
||||
>K : Symbol(K, Decl(recursiveMappedTypes.ts, 85, 23))
|
||||
>ThemeType : Symbol(ThemeType, Decl(recursiveMappedTypes.ts, 85, 49))
|
||||
>ThemeType : Symbol(ThemeType, Decl(recursiveMappedTypes.ts, 85, 49))
|
||||
>TVal : Symbol(TVal, Decl(recursiveMappedTypes.ts, 85, 60))
|
||||
|
||||
ThemeType[K] extends TVal[] ? number :
|
||||
>ThemeType : Symbol(ThemeType, Decl(recursiveMappedTypes.ts, 85, 49))
|
||||
>K : Symbol(K, Decl(recursiveMappedTypes.ts, 85, 23))
|
||||
>TVal : Symbol(TVal, Decl(recursiveMappedTypes.ts, 85, 60))
|
||||
|
||||
ThemeType[K] extends Record<infer E, TVal> ? E :
|
||||
>ThemeType : Symbol(ThemeType, Decl(recursiveMappedTypes.ts, 85, 49))
|
||||
>K : Symbol(K, Decl(recursiveMappedTypes.ts, 85, 23))
|
||||
>Record : Symbol(Record, Decl(lib.es5.d.ts, --, --))
|
||||
>E : Symbol(E, Decl(recursiveMappedTypes.ts, 87, 37))
|
||||
>TVal : Symbol(TVal, Decl(recursiveMappedTypes.ts, 85, 60))
|
||||
>E : Symbol(E, Decl(recursiveMappedTypes.ts, 87, 37))
|
||||
|
||||
ThemeType[K] extends ObjectOrArray<infer F> ? F : never;
|
||||
>ThemeType : Symbol(ThemeType, Decl(recursiveMappedTypes.ts, 85, 49))
|
||||
>K : Symbol(K, Decl(recursiveMappedTypes.ts, 85, 23))
|
||||
>ObjectOrArray : Symbol(ObjectOrArray, Decl(recursiveMappedTypes.ts, 82, 85))
|
||||
>F : Symbol(F, Decl(recursiveMappedTypes.ts, 88, 44))
|
||||
>F : Symbol(F, Decl(recursiveMappedTypes.ts, 88, 44))
|
||||
|
||||
export type Foo<T> = T extends { [P in infer E]: any } ? E : never;
|
||||
>Foo : Symbol(Foo, Decl(recursiveMappedTypes.ts, 88, 60))
|
||||
>T : Symbol(T, Decl(recursiveMappedTypes.ts, 90, 16))
|
||||
>T : Symbol(T, Decl(recursiveMappedTypes.ts, 90, 16))
|
||||
>P : Symbol(P, Decl(recursiveMappedTypes.ts, 90, 34))
|
||||
>E : Symbol(E, Decl(recursiveMappedTypes.ts, 90, 44))
|
||||
>E : Symbol(E, Decl(recursiveMappedTypes.ts, 90, 44))
|
||||
|
||||
|
||||
@@ -133,3 +133,21 @@ x.type;
|
||||
>x : Child<ListWidget>
|
||||
>type : any
|
||||
|
||||
// Repros from #41790
|
||||
|
||||
export type TV<T, K extends keyof T> = T[K] extends Record<infer E, any> ? E : never;
|
||||
>TV : TV<T, K>
|
||||
|
||||
export type ObjectOrArray<T, K extends keyof any = keyof any> = T[] | Record<K, T | Record<K, T> | T[]>;
|
||||
>ObjectOrArray : ObjectOrArray<T, K>
|
||||
|
||||
export type ThemeValue<K extends keyof ThemeType, ThemeType, TVal = any> =
|
||||
>ThemeValue : ThemeValue<K, ThemeType, TVal>
|
||||
|
||||
ThemeType[K] extends TVal[] ? number :
|
||||
ThemeType[K] extends Record<infer E, TVal> ? E :
|
||||
ThemeType[K] extends ObjectOrArray<infer F> ? F : never;
|
||||
|
||||
export type Foo<T> = T extends { [P in infer E]: any } ? E : never;
|
||||
>Foo : Foo<T>
|
||||
|
||||
|
||||
@@ -79,3 +79,15 @@ type ListChild = Child<ListWidget>
|
||||
|
||||
declare let x: ListChild;
|
||||
x.type;
|
||||
|
||||
// Repros from #41790
|
||||
|
||||
export type TV<T, K extends keyof T> = T[K] extends Record<infer E, any> ? E : never;
|
||||
|
||||
export type ObjectOrArray<T, K extends keyof any = keyof any> = T[] | Record<K, T | Record<K, T> | T[]>;
|
||||
export type ThemeValue<K extends keyof ThemeType, ThemeType, TVal = any> =
|
||||
ThemeType[K] extends TVal[] ? number :
|
||||
ThemeType[K] extends Record<infer E, TVal> ? E :
|
||||
ThemeType[K] extends ObjectOrArray<infer F> ? F : never;
|
||||
|
||||
export type Foo<T> = T extends { [P in infer E]: any } ? E : never;
|
||||
|
||||
Reference in New Issue
Block a user