mirror of
https://github.com/microsoft/TypeScript.git
synced 2025-11-18 17:21:48 +00:00
Merge pull request #21134 from Microsoft/fix-recursive-mapped-type-infinite-recursion
Fix recursive mapped type infinite recursion
This commit is contained in:
+11
-6
@@ -530,6 +530,7 @@ namespace ts {
|
||||
ResolvedBaseConstructorType,
|
||||
DeclaredType,
|
||||
ResolvedReturnType,
|
||||
ResolvedBaseConstraint,
|
||||
}
|
||||
|
||||
const enum CheckMode {
|
||||
@@ -4254,7 +4255,7 @@ namespace ts {
|
||||
return -1;
|
||||
}
|
||||
|
||||
function hasType(target: TypeSystemEntity, propertyName: TypeSystemPropertyName): Type {
|
||||
function hasType(target: TypeSystemEntity, propertyName: TypeSystemPropertyName): Type | boolean {
|
||||
if (propertyName === TypeSystemPropertyName.Type) {
|
||||
return getSymbolLinks(<Symbol>target).type;
|
||||
}
|
||||
@@ -4267,6 +4268,10 @@ namespace ts {
|
||||
if (propertyName === TypeSystemPropertyName.ResolvedReturnType) {
|
||||
return (<Signature>target).resolvedReturnType;
|
||||
}
|
||||
if (propertyName === TypeSystemPropertyName.ResolvedBaseConstraint) {
|
||||
const bc = (<TypeParameter | UnionOrIntersectionType>target).resolvedBaseConstraint;
|
||||
return bc && bc !== circularConstraintType;
|
||||
}
|
||||
|
||||
Debug.fail("Unhandled TypeSystemPropertyName " + propertyName);
|
||||
}
|
||||
@@ -6500,23 +6505,23 @@ namespace ts {
|
||||
* circularly references the type variable.
|
||||
*/
|
||||
function getResolvedBaseConstraint(type: TypeVariable | UnionOrIntersectionType): Type {
|
||||
let typeStack: Type[];
|
||||
let circular: boolean;
|
||||
if (!type.resolvedBaseConstraint) {
|
||||
typeStack = [];
|
||||
const constraint = getBaseConstraint(type);
|
||||
type.resolvedBaseConstraint = circular ? circularConstraintType : getTypeWithThisArgument(constraint || noConstraintType, type);
|
||||
}
|
||||
return type.resolvedBaseConstraint;
|
||||
|
||||
function getBaseConstraint(t: Type): Type {
|
||||
if (contains(typeStack, t)) {
|
||||
if (!pushTypeResolution(t, TypeSystemPropertyName.ResolvedBaseConstraint)) {
|
||||
circular = true;
|
||||
return undefined;
|
||||
}
|
||||
typeStack.push(t);
|
||||
const result = computeBaseConstraint(t);
|
||||
typeStack.pop();
|
||||
if (!popTypeResolution()) {
|
||||
circular = true;
|
||||
return undefined;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,11 @@
|
||||
tests/cases/compiler/incorrectRecursiveMappedTypeConstraint.ts(2,32): error TS2313: Type parameter 'P' has a circular constraint.
|
||||
|
||||
|
||||
==== tests/cases/compiler/incorrectRecursiveMappedTypeConstraint.ts (1 errors) ====
|
||||
// #17847
|
||||
function sum<T extends { [P in T]: number }, K extends keyof T>(n: number, v: T, k: K) {
|
||||
~
|
||||
!!! error TS2313: Type parameter 'P' has a circular constraint.
|
||||
n += v[k];
|
||||
}
|
||||
|
||||
@@ -0,0 +1,12 @@
|
||||
//// [incorrectRecursiveMappedTypeConstraint.ts]
|
||||
// #17847
|
||||
function sum<T extends { [P in T]: number }, K extends keyof T>(n: number, v: T, k: K) {
|
||||
n += v[k];
|
||||
}
|
||||
|
||||
|
||||
//// [incorrectRecursiveMappedTypeConstraint.js]
|
||||
// #17847
|
||||
function sum(n, v, k) {
|
||||
n += v[k];
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
=== tests/cases/compiler/incorrectRecursiveMappedTypeConstraint.ts ===
|
||||
// #17847
|
||||
function sum<T extends { [P in T]: number }, K extends keyof T>(n: number, v: T, k: K) {
|
||||
>sum : Symbol(sum, Decl(incorrectRecursiveMappedTypeConstraint.ts, 0, 0))
|
||||
>T : Symbol(T, Decl(incorrectRecursiveMappedTypeConstraint.ts, 1, 13))
|
||||
>P : Symbol(P, Decl(incorrectRecursiveMappedTypeConstraint.ts, 1, 26))
|
||||
>T : Symbol(T, Decl(incorrectRecursiveMappedTypeConstraint.ts, 1, 13))
|
||||
>K : Symbol(K, Decl(incorrectRecursiveMappedTypeConstraint.ts, 1, 44))
|
||||
>T : Symbol(T, Decl(incorrectRecursiveMappedTypeConstraint.ts, 1, 13))
|
||||
>n : Symbol(n, Decl(incorrectRecursiveMappedTypeConstraint.ts, 1, 64))
|
||||
>v : Symbol(v, Decl(incorrectRecursiveMappedTypeConstraint.ts, 1, 74))
|
||||
>T : Symbol(T, Decl(incorrectRecursiveMappedTypeConstraint.ts, 1, 13))
|
||||
>k : Symbol(k, Decl(incorrectRecursiveMappedTypeConstraint.ts, 1, 80))
|
||||
>K : Symbol(K, Decl(incorrectRecursiveMappedTypeConstraint.ts, 1, 44))
|
||||
|
||||
n += v[k];
|
||||
>n : Symbol(n, Decl(incorrectRecursiveMappedTypeConstraint.ts, 1, 64))
|
||||
>v : Symbol(v, Decl(incorrectRecursiveMappedTypeConstraint.ts, 1, 74))
|
||||
>k : Symbol(k, Decl(incorrectRecursiveMappedTypeConstraint.ts, 1, 80))
|
||||
}
|
||||
|
||||
@@ -0,0 +1,23 @@
|
||||
=== tests/cases/compiler/incorrectRecursiveMappedTypeConstraint.ts ===
|
||||
// #17847
|
||||
function sum<T extends { [P in T]: number }, K extends keyof T>(n: number, v: T, k: K) {
|
||||
>sum : <T extends { [x: string]: number; }, K extends keyof T>(n: number, v: T, k: K) => void
|
||||
>T : T
|
||||
>P : P
|
||||
>T : T
|
||||
>K : K
|
||||
>T : T
|
||||
>n : number
|
||||
>v : T
|
||||
>T : T
|
||||
>k : K
|
||||
>K : K
|
||||
|
||||
n += v[k];
|
||||
>n += v[k] : number
|
||||
>n : number
|
||||
>v[k] : T[K]
|
||||
>v : T
|
||||
>k : K
|
||||
}
|
||||
|
||||
@@ -1,25 +1,34 @@
|
||||
tests/cases/conformance/types/mapped/recursiveMappedTypes.ts(3,6): error TS2456: Type alias 'Recurse' circularly references itself.
|
||||
tests/cases/conformance/types/mapped/recursiveMappedTypes.ts(4,11): error TS2313: Type parameter 'K' has a circular constraint.
|
||||
tests/cases/conformance/types/mapped/recursiveMappedTypes.ts(7,6): error TS2456: Type alias 'Recurse1' circularly references itself.
|
||||
tests/cases/conformance/types/mapped/recursiveMappedTypes.ts(8,11): error TS2313: Type parameter 'K' has a circular constraint.
|
||||
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 (3 errors) ====
|
||||
==== tests/cases/conformance/types/mapped/recursiveMappedTypes.ts (6 errors) ====
|
||||
// Recursive mapped types simply appear empty
|
||||
|
||||
type Recurse = {
|
||||
~~~~~~~
|
||||
!!! error TS2456: Type alias 'Recurse' circularly references itself.
|
||||
[K in keyof Recurse]: Recurse[K]
|
||||
~~~~~~~~~~~~~
|
||||
!!! error TS2313: Type parameter 'K' has a circular constraint.
|
||||
}
|
||||
|
||||
type Recurse1 = {
|
||||
~~~~~~~~
|
||||
!!! error TS2456: Type alias 'Recurse1' circularly references itself.
|
||||
[K in keyof Recurse2]: Recurse2[K]
|
||||
~~~~~~~~~~~~~~
|
||||
!!! error TS2313: Type parameter 'K' has a circular constraint.
|
||||
}
|
||||
|
||||
type Recurse2 = {
|
||||
~~~~~~~~
|
||||
!!! error TS2456: Type alias 'Recurse2' circularly references itself.
|
||||
[K in keyof Recurse1]: Recurse1[K]
|
||||
~~~~~~~~~~~~~~
|
||||
!!! error TS2313: Type parameter 'K' has a circular constraint.
|
||||
}
|
||||
@@ -0,0 +1,4 @@
|
||||
// #17847
|
||||
function sum<T extends { [P in T]: number }, K extends keyof T>(n: number, v: T, k: K) {
|
||||
n += v[k];
|
||||
}
|
||||
Reference in New Issue
Block a user