From 189d4e9072c482206879d047153a606a095d5642 Mon Sep 17 00:00:00 2001 From: Wesley Wigham Date: Fri, 10 Jul 2020 10:47:58 -0700 Subject: [PATCH] Flag mapped types with circular property types and do not attempt to print them structurally --- src/compiler/checker.ts | 5 +++-- src/compiler/types.ts | 1 + ...velyExpandingUnionNoStackoverflow.errors.txt | 12 ++++++++++++ .../recursivelyExpandingUnionNoStackoverflow.js | 6 ++++++ ...rsivelyExpandingUnionNoStackoverflow.symbols | 17 +++++++++++++++++ ...cursivelyExpandingUnionNoStackoverflow.types | 7 +++++++ .../recursivelyExpandingUnionNoStackoverflow.ts | 3 +++ 7 files changed, 49 insertions(+), 2 deletions(-) create mode 100644 tests/baselines/reference/recursivelyExpandingUnionNoStackoverflow.errors.txt create mode 100644 tests/baselines/reference/recursivelyExpandingUnionNoStackoverflow.js create mode 100644 tests/baselines/reference/recursivelyExpandingUnionNoStackoverflow.symbols create mode 100644 tests/baselines/reference/recursivelyExpandingUnionNoStackoverflow.types create mode 100644 tests/cases/compiler/recursivelyExpandingUnionNoStackoverflow.ts diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 10f93e8f14abd..f5481ba03d744 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -4572,8 +4572,8 @@ namespace ts { } function createTypeNodeFromObjectType(type: ObjectType): TypeNode { - if (isGenericMappedType(type)) { - return createMappedTypeNodeFromType(type); + if (isGenericMappedType(type) || (type as MappedType).containsError) { + return createMappedTypeNodeFromType(type as MappedType); } const resolved = resolveStructuredTypeMembers(type); @@ -10309,6 +10309,7 @@ namespace ts { function getTypeOfMappedSymbol(symbol: MappedSymbol) { if (!symbol.type) { if (!pushTypeResolution(symbol, TypeSystemPropertyName.Type)) { + symbol.mappedType.containsError = true; return errorType; } const templateType = getTemplateTypeFromMappedType(symbol.mappedType.target || symbol.mappedType); diff --git a/src/compiler/types.ts b/src/compiler/types.ts index 811b29abda6ce..9953048202b8f 100644 --- a/src/compiler/types.ts +++ b/src/compiler/types.ts @@ -5168,6 +5168,7 @@ namespace ts { templateType?: Type; modifiersType?: Type; resolvedApparentType?: Type; + containsError?: boolean; } export interface EvolvingArrayType extends ObjectType { diff --git a/tests/baselines/reference/recursivelyExpandingUnionNoStackoverflow.errors.txt b/tests/baselines/reference/recursivelyExpandingUnionNoStackoverflow.errors.txt new file mode 100644 index 0000000000000..b6eb0fbecc9a8 --- /dev/null +++ b/tests/baselines/reference/recursivelyExpandingUnionNoStackoverflow.errors.txt @@ -0,0 +1,12 @@ +tests/cases/compiler/recursivelyExpandingUnionNoStackoverflow.ts(3,10): error TS2589: Type instantiation is excessively deep and possibly infinite. +tests/cases/compiler/recursivelyExpandingUnionNoStackoverflow.ts(3,10): error TS2615: Type of property 'M' circularly references itself in mapped type '{ [P in "M"]: any; }'. + + +==== tests/cases/compiler/recursivelyExpandingUnionNoStackoverflow.ts (2 errors) ==== + type N = T | { [P in K]: N }[K]; + + type M = N; + ~~~~~~~~~~~~~~ +!!! error TS2589: Type instantiation is excessively deep and possibly infinite. + ~~~~~~~~~~~~~~ +!!! error TS2615: Type of property 'M' circularly references itself in mapped type '{ [P in "M"]: any; }'. \ No newline at end of file diff --git a/tests/baselines/reference/recursivelyExpandingUnionNoStackoverflow.js b/tests/baselines/reference/recursivelyExpandingUnionNoStackoverflow.js new file mode 100644 index 0000000000000..b300f70d5ac46 --- /dev/null +++ b/tests/baselines/reference/recursivelyExpandingUnionNoStackoverflow.js @@ -0,0 +1,6 @@ +//// [recursivelyExpandingUnionNoStackoverflow.ts] +type N = T | { [P in K]: N }[K]; + +type M = N; + +//// [recursivelyExpandingUnionNoStackoverflow.js] diff --git a/tests/baselines/reference/recursivelyExpandingUnionNoStackoverflow.symbols b/tests/baselines/reference/recursivelyExpandingUnionNoStackoverflow.symbols new file mode 100644 index 0000000000000..1f0465aeac0a1 --- /dev/null +++ b/tests/baselines/reference/recursivelyExpandingUnionNoStackoverflow.symbols @@ -0,0 +1,17 @@ +=== tests/cases/compiler/recursivelyExpandingUnionNoStackoverflow.ts === +type N = T | { [P in K]: N }[K]; +>N : Symbol(N, Decl(recursivelyExpandingUnionNoStackoverflow.ts, 0, 0)) +>T : Symbol(T, Decl(recursivelyExpandingUnionNoStackoverflow.ts, 0, 7)) +>K : Symbol(K, Decl(recursivelyExpandingUnionNoStackoverflow.ts, 0, 9)) +>T : Symbol(T, Decl(recursivelyExpandingUnionNoStackoverflow.ts, 0, 7)) +>P : Symbol(P, Decl(recursivelyExpandingUnionNoStackoverflow.ts, 0, 37)) +>K : Symbol(K, Decl(recursivelyExpandingUnionNoStackoverflow.ts, 0, 9)) +>N : Symbol(N, Decl(recursivelyExpandingUnionNoStackoverflow.ts, 0, 0)) +>T : Symbol(T, Decl(recursivelyExpandingUnionNoStackoverflow.ts, 0, 7)) +>K : Symbol(K, Decl(recursivelyExpandingUnionNoStackoverflow.ts, 0, 9)) +>K : Symbol(K, Decl(recursivelyExpandingUnionNoStackoverflow.ts, 0, 9)) + +type M = N; +>M : Symbol(M, Decl(recursivelyExpandingUnionNoStackoverflow.ts, 0, 59)) +>N : Symbol(N, Decl(recursivelyExpandingUnionNoStackoverflow.ts, 0, 0)) + diff --git a/tests/baselines/reference/recursivelyExpandingUnionNoStackoverflow.types b/tests/baselines/reference/recursivelyExpandingUnionNoStackoverflow.types new file mode 100644 index 0000000000000..53ee73287b6f2 --- /dev/null +++ b/tests/baselines/reference/recursivelyExpandingUnionNoStackoverflow.types @@ -0,0 +1,7 @@ +=== tests/cases/compiler/recursivelyExpandingUnionNoStackoverflow.ts === +type N = T | { [P in K]: N }[K]; +>N : N + +type M = N; +>M : any + diff --git a/tests/cases/compiler/recursivelyExpandingUnionNoStackoverflow.ts b/tests/cases/compiler/recursivelyExpandingUnionNoStackoverflow.ts new file mode 100644 index 0000000000000..e6ff1a3d5035d --- /dev/null +++ b/tests/cases/compiler/recursivelyExpandingUnionNoStackoverflow.ts @@ -0,0 +1,3 @@ +type N = T | { [P in K]: N }[K]; + +type M = N; \ No newline at end of file