From c5ab4735ac01d316e4384e5ea398bd8d271c2ff0 Mon Sep 17 00:00:00 2001 From: Anders Hejlsberg Date: Wed, 16 Nov 2016 06:48:51 -0800 Subject: [PATCH 1/3] Resolve upfront so recursive mapped types appear empty --- src/compiler/checker.ts | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 44bbfbc9ad5..846bb288d6b 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -4489,6 +4489,8 @@ namespace ts { const members: SymbolTable = createMap(); let stringIndexInfo: IndexInfo; let numberIndexInfo: IndexInfo; + // Resolve upfront such that recursive references see an empty object type. + setStructuredTypeMembers(type, emptySymbols, emptyArray, emptyArray, undefined, undefined); // In { [P in K]: T }, we refer to P as the type parameter type, K as the constraint type, // and T as the template type. const typeParameter = getTypeParameterFromMappedType(type); From c00a04d781dae1dff928174427e926f5b144c706 Mon Sep 17 00:00:00 2001 From: Anders Hejlsberg Date: Wed, 16 Nov 2016 06:49:04 -0800 Subject: [PATCH 2/3] Add tests --- .../types/mapped/recursiveMappedTypes.ts | 15 +++++++++++++++ 1 file changed, 15 insertions(+) create mode 100644 tests/cases/conformance/types/mapped/recursiveMappedTypes.ts diff --git a/tests/cases/conformance/types/mapped/recursiveMappedTypes.ts b/tests/cases/conformance/types/mapped/recursiveMappedTypes.ts new file mode 100644 index 00000000000..7a78ad9dc4a --- /dev/null +++ b/tests/cases/conformance/types/mapped/recursiveMappedTypes.ts @@ -0,0 +1,15 @@ +// @declaration: true + +// Recursive mapped types simply appear empty + +type Recurse = { + [K in keyof Recurse]: Recurse[K] +} + +type Recurse1 = { + [K in keyof Recurse2]: Recurse2[K] +} + +type Recurse2 = { + [K in keyof Recurse1]: Recurse1[K] +} \ No newline at end of file From 78726aeb3d46b4535a2f2a49b321c6ad1f413b1a Mon Sep 17 00:00:00 2001 From: Anders Hejlsberg Date: Wed, 16 Nov 2016 06:49:15 -0800 Subject: [PATCH 3/3] Accept new baselines --- .../reference/recursiveMappedTypes.js | 30 +++++++++++++++++ .../reference/recursiveMappedTypes.symbols | 33 +++++++++++++++++++ .../reference/recursiveMappedTypes.types | 33 +++++++++++++++++++ 3 files changed, 96 insertions(+) create mode 100644 tests/baselines/reference/recursiveMappedTypes.js create mode 100644 tests/baselines/reference/recursiveMappedTypes.symbols create mode 100644 tests/baselines/reference/recursiveMappedTypes.types diff --git a/tests/baselines/reference/recursiveMappedTypes.js b/tests/baselines/reference/recursiveMappedTypes.js new file mode 100644 index 00000000000..dfe69457ed7 --- /dev/null +++ b/tests/baselines/reference/recursiveMappedTypes.js @@ -0,0 +1,30 @@ +//// [recursiveMappedTypes.ts] + +// Recursive mapped types simply appear empty + +type Recurse = { + [K in keyof Recurse]: Recurse[K] +} + +type Recurse1 = { + [K in keyof Recurse2]: Recurse2[K] +} + +type Recurse2 = { + [K in keyof Recurse1]: Recurse1[K] +} + +//// [recursiveMappedTypes.js] +// Recursive mapped types simply appear empty + + +//// [recursiveMappedTypes.d.ts] +declare type Recurse = { + [K in keyof Recurse]: Recurse[K]; +}; +declare type Recurse1 = { + [K in keyof Recurse2]: Recurse2[K]; +}; +declare type Recurse2 = { + [K in keyof Recurse1]: Recurse1[K]; +}; diff --git a/tests/baselines/reference/recursiveMappedTypes.symbols b/tests/baselines/reference/recursiveMappedTypes.symbols new file mode 100644 index 00000000000..ae4ca8d9cc9 --- /dev/null +++ b/tests/baselines/reference/recursiveMappedTypes.symbols @@ -0,0 +1,33 @@ +=== tests/cases/conformance/types/mapped/recursiveMappedTypes.ts === + +// Recursive mapped types simply appear empty + +type Recurse = { +>Recurse : Symbol(Recurse, Decl(recursiveMappedTypes.ts, 0, 0)) + + [K in keyof Recurse]: Recurse[K] +>K : Symbol(K, Decl(recursiveMappedTypes.ts, 4, 5)) +>Recurse : Symbol(Recurse, Decl(recursiveMappedTypes.ts, 0, 0)) +>Recurse : Symbol(Recurse, Decl(recursiveMappedTypes.ts, 0, 0)) +>K : Symbol(K, Decl(recursiveMappedTypes.ts, 4, 5)) +} + +type Recurse1 = { +>Recurse1 : Symbol(Recurse1, Decl(recursiveMappedTypes.ts, 5, 1)) + + [K in keyof Recurse2]: Recurse2[K] +>K : Symbol(K, Decl(recursiveMappedTypes.ts, 8, 5)) +>Recurse2 : Symbol(Recurse2, Decl(recursiveMappedTypes.ts, 9, 1)) +>Recurse2 : Symbol(Recurse2, Decl(recursiveMappedTypes.ts, 9, 1)) +>K : Symbol(K, Decl(recursiveMappedTypes.ts, 8, 5)) +} + +type Recurse2 = { +>Recurse2 : Symbol(Recurse2, Decl(recursiveMappedTypes.ts, 9, 1)) + + [K in keyof Recurse1]: Recurse1[K] +>K : Symbol(K, Decl(recursiveMappedTypes.ts, 12, 5)) +>Recurse1 : Symbol(Recurse1, Decl(recursiveMappedTypes.ts, 5, 1)) +>Recurse1 : Symbol(Recurse1, Decl(recursiveMappedTypes.ts, 5, 1)) +>K : Symbol(K, Decl(recursiveMappedTypes.ts, 12, 5)) +} diff --git a/tests/baselines/reference/recursiveMappedTypes.types b/tests/baselines/reference/recursiveMappedTypes.types new file mode 100644 index 00000000000..2c60bc8b68a --- /dev/null +++ b/tests/baselines/reference/recursiveMappedTypes.types @@ -0,0 +1,33 @@ +=== tests/cases/conformance/types/mapped/recursiveMappedTypes.ts === + +// Recursive mapped types simply appear empty + +type Recurse = { +>Recurse : Recurse + + [K in keyof Recurse]: Recurse[K] +>K : K +>Recurse : Recurse +>Recurse : Recurse +>K : K +} + +type Recurse1 = { +>Recurse1 : Recurse1 + + [K in keyof Recurse2]: Recurse2[K] +>K : K +>Recurse2 : Recurse2 +>Recurse2 : Recurse2 +>K : K +} + +type Recurse2 = { +>Recurse2 : Recurse2 + + [K in keyof Recurse1]: Recurse1[K] +>K : K +>Recurse1 : Recurse1 +>Recurse1 : Recurse1 +>K : K +}