From 6839973bf7703c613fa15dade4a30860533214f2 Mon Sep 17 00:00:00 2001 From: Wesley Wigham Date: Wed, 10 Jul 2019 17:12:20 -0700 Subject: [PATCH] Generate a unique type parameter name for each nested type parameter (#31544) * Generate a unique type parameter name for each nested type parameter * Add testcase from 31605 * Fix typo * Liiiiiine eeeendingggggss --- src/compiler/checker.ts | 52 +++-- ...iveInternalTypesProduceUniqueTypeParams.js | 164 ++++++++++++++ ...ternalTypesProduceUniqueTypeParams.symbols | 206 +++++++++++++++++ ...InternalTypesProduceUniqueTypeParams.types | 212 ++++++++++++++++++ ...iveInternalTypesProduceUniqueTypeParams.ts | 42 ++++ 5 files changed, 658 insertions(+), 18 deletions(-) create mode 100644 tests/baselines/reference/declarationsWithRecursiveInternalTypesProduceUniqueTypeParams.js create mode 100644 tests/baselines/reference/declarationsWithRecursiveInternalTypesProduceUniqueTypeParams.symbols create mode 100644 tests/baselines/reference/declarationsWithRecursiveInternalTypesProduceUniqueTypeParams.types create mode 100644 tests/cases/compiler/declarationsWithRecursiveInternalTypesProduceUniqueTypeParams.ts diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index b3dfbb94616..73e81913d6c 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -3699,14 +3699,10 @@ namespace ts { return createInferTypeNode(typeParameterToDeclarationWithConstraint(type as TypeParameter, context, /*constraintNode*/ undefined)); } if (context.flags & NodeBuilderFlags.GenerateNamesForShadowedTypeParams && - type.flags & TypeFlags.TypeParameter && - length(type.symbol.declarations) && - isTypeParameterDeclaration(type.symbol.declarations[0]) && - typeParameterShadowsNameInScope(type, context) && !isTypeSymbolAccessible(type.symbol, context.enclosingDeclaration)) { - const name = (type.symbol.declarations[0] as TypeParameterDeclaration).name; + const name = typeParameterToName(type, context); context.approximateLength += idText(name).length; - return createTypeReferenceNode(getGeneratedNameForNode(name, GeneratedIdentifierFlags.Optimistic | GeneratedIdentifierFlags.ReservedInNestedScopes), /*typeArguments*/ undefined); + return createTypeReferenceNode(createIdentifier(idText(name)), /*typeArguments*/ undefined); } // Ignore constraint/default when creating a usage (as opposed to declaration) of a type parameter. return type.symbol @@ -4237,21 +4233,10 @@ namespace ts { return createSignatureDeclaration(kind, typeParameters, parameters, returnTypeNode, typeArguments); } - function typeParameterShadowsNameInScope(type: TypeParameter, context: NodeBuilderContext) { - return !!resolveName(context.enclosingDeclaration, type.symbol.escapedName, SymbolFlags.Type, /*nameNotFoundArg*/ undefined, type.symbol.escapedName, /*isUse*/ false); - } - function typeParameterToDeclarationWithConstraint(type: TypeParameter, context: NodeBuilderContext, constraintNode: TypeNode | undefined): TypeParameterDeclaration { const savedContextFlags = context.flags; context.flags &= ~NodeBuilderFlags.WriteTypeParametersInQualifiedName; // Avoids potential infinite loop when building for a claimspace with a generic - const shouldUseGeneratedName = - context.flags & NodeBuilderFlags.GenerateNamesForShadowedTypeParams && - type.symbol.declarations && type.symbol.declarations[0] && - isTypeParameterDeclaration(type.symbol.declarations[0]) && - typeParameterShadowsNameInScope(type, context); - const name = shouldUseGeneratedName - ? getGeneratedNameForNode((type.symbol.declarations[0] as TypeParameterDeclaration).name, GeneratedIdentifierFlags.Optimistic | GeneratedIdentifierFlags.ReservedInNestedScopes) - : symbolToName(type.symbol, context, SymbolFlags.Type, /*expectsIdentifier*/ true); + const name = typeParameterToName(type, context); const defaultParameter = getDefaultFromTypeParameter(type); const defaultParameterNode = defaultParameter && typeToTypeNodeHelper(defaultParameter, context); context.flags = savedContextFlags; @@ -4584,6 +4569,35 @@ namespace ts { } } + function typeParameterShadowsNameInScope(escapedName: __String, context: NodeBuilderContext) { + return !!resolveName(context.enclosingDeclaration, escapedName, SymbolFlags.Type, /*nameNotFoundArg*/ undefined, escapedName, /*isUse*/ false); + } + + function typeParameterToName(type: TypeParameter, context: NodeBuilderContext) { + if (context.flags & NodeBuilderFlags.GenerateNamesForShadowedTypeParams && context.typeParameterNames) { + const cached = context.typeParameterNames.get("" + getTypeId(type)); + if (cached) { + return cached; + } + } + let result = symbolToName(type.symbol, context, SymbolFlags.Type, /*expectsIdentifier*/ true); + if (context.flags & NodeBuilderFlags.GenerateNamesForShadowedTypeParams) { + const rawtext = result.escapedText as string; + let i = 0; + let text = rawtext; + while ((context.typeParameterNamesByText && context.typeParameterNamesByText.get(text)) || typeParameterShadowsNameInScope(text as __String, context)) { + i++; + text = `${rawtext}_${i}`; + } + if (text !== rawtext) { + result = createIdentifier(text, result.typeArguments); + } + (context.typeParameterNames || (context.typeParameterNames = createMap())).set("" + getTypeId(type), result); + (context.typeParameterNamesByText || (context.typeParameterNamesByText = createMap())).set(result.escapedText as string, true); + } + return result; + } + function symbolToName(symbol: Symbol, context: NodeBuilderContext, meaning: SymbolFlags, expectsIdentifier: true): Identifier; function symbolToName(symbol: Symbol, context: NodeBuilderContext, meaning: SymbolFlags, expectsIdentifier: false): EntityName; function symbolToName(symbol: Symbol, context: NodeBuilderContext, meaning: SymbolFlags, expectsIdentifier: boolean): EntityName { @@ -4745,6 +4759,8 @@ namespace ts { approximateLength: number; truncating?: boolean; typeParameterSymbolList?: Map; + typeParameterNames?: Map; + typeParameterNamesByText?: Map; } function isDefaultBindingContext(location: Node) { diff --git a/tests/baselines/reference/declarationsWithRecursiveInternalTypesProduceUniqueTypeParams.js b/tests/baselines/reference/declarationsWithRecursiveInternalTypesProduceUniqueTypeParams.js new file mode 100644 index 00000000000..913e82292bf --- /dev/null +++ b/tests/baselines/reference/declarationsWithRecursiveInternalTypesProduceUniqueTypeParams.js @@ -0,0 +1,164 @@ +//// [declarationsWithRecursiveInternalTypesProduceUniqueTypeParams.ts] +// Note that both of the following have an `any` in their return type from where we bottom out the type printout +// for having too many instances of the same symbol nesting. + +// Slightly simplified repro from https://github.com/microsoft/TypeScript/issues/30732 so it's easier to read and debug +export type Key = keyof U; +export type Value, U> = U[K]; +export const updateIfChanged = (t: T) => { + const reduce = (u: U, update: (u: U) => T) => { + const set = (newU: U) => Object.is(u, newU) ? t : update(newU); + return Object.assign( + >(key: K) => + reduce>(u[key as keyof U] as Value, (v: Value) => { + return update(Object.assign(Array.isArray(u) ? [] : {}, u, { [key]: v })); + }), + { map: (updater: (u: U) => U) => set(updater(u)), set }); + }; + return reduce(t, (t: T) => t); +}; + +// example from https://github.com/microsoft/TypeScript/issues/31605 + +export const testRecFun = (parent: T) => { + return { + result: parent, + deeper: (child: U) => + testRecFun({ ...parent, ...child }) + }; +} + + +let p1 = testRecFun({ one: '1' }) +void p1.result.one; +let p2 = p1.deeper({ two: '2' }) +void p2.result.one; +void p2.result.two; +let p3 = p2.deeper({ three: '3' }) +void p3.result.one; +void p3.result.two; +void p3.result.three; + + +//// [declarationsWithRecursiveInternalTypesProduceUniqueTypeParams.js] +"use strict"; +// Note that both of the following have an `any` in their return type from where we bottom out the type printout +// for having too many instances of the same symbol nesting. +var __assign = (this && this.__assign) || function () { + __assign = Object.assign || function(t) { + for (var s, i = 1, n = arguments.length; i < n; i++) { + s = arguments[i]; + for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p)) + t[p] = s[p]; + } + return t; + }; + return __assign.apply(this, arguments); +}; +exports.__esModule = true; +exports.updateIfChanged = function (t) { + var reduce = function (u, update) { + var set = function (newU) { return Object.is(u, newU) ? t : update(newU); }; + return Object.assign(function (key) { + return reduce(u[key], function (v) { + var _a; + return update(Object.assign(Array.isArray(u) ? [] : {}, u, (_a = {}, _a[key] = v, _a))); + }); + }, { map: function (updater) { return set(updater(u)); }, set: set }); + }; + return reduce(t, function (t) { return t; }); +}; +// example from https://github.com/microsoft/TypeScript/issues/31605 +exports.testRecFun = function (parent) { + return { + result: parent, + deeper: function (child) { + return exports.testRecFun(__assign({}, parent, child)); + } + }; +}; +var p1 = exports.testRecFun({ one: '1' }); +void p1.result.one; +var p2 = p1.deeper({ two: '2' }); +void p2.result.one; +void p2.result.two; +var p3 = p2.deeper({ three: '3' }); +void p3.result.one; +void p3.result.two; +void p3.result.three; + + +//// [declarationsWithRecursiveInternalTypesProduceUniqueTypeParams.d.ts] +export declare type Key = keyof U; +export declare type Value, U> = U[K]; +export declare const updateIfChanged: (t: T) => ((key: K) => ((key: K_1) => ((key: K_2) => ((key: K_3) => ((key: K_4) => ((key: K_5) => ((key: K_6) => ((key: K_7) => ((key: K_8) => ((key: K_9) => ((key: K_10) => any & { + map: (updater: (u: T[K][K_1][K_2][K_3][K_4][K_5][K_6][K_7][K_8][K_9][K_10]) => T[K][K_1][K_2][K_3][K_4][K_5][K_6][K_7][K_8][K_9][K_10]) => T; + set: (newU: T[K][K_1][K_2][K_3][K_4][K_5][K_6][K_7][K_8][K_9][K_10]) => T; +}) & { + map: (updater: (u: T[K][K_1][K_2][K_3][K_4][K_5][K_6][K_7][K_8][K_9]) => T[K][K_1][K_2][K_3][K_4][K_5][K_6][K_7][K_8][K_9]) => T; + set: (newU: T[K][K_1][K_2][K_3][K_4][K_5][K_6][K_7][K_8][K_9]) => T; +}) & { + map: (updater: (u: T[K][K_1][K_2][K_3][K_4][K_5][K_6][K_7][K_8]) => T[K][K_1][K_2][K_3][K_4][K_5][K_6][K_7][K_8]) => T; + set: (newU: T[K][K_1][K_2][K_3][K_4][K_5][K_6][K_7][K_8]) => T; +}) & { + map: (updater: (u: T[K][K_1][K_2][K_3][K_4][K_5][K_6][K_7]) => T[K][K_1][K_2][K_3][K_4][K_5][K_6][K_7]) => T; + set: (newU: T[K][K_1][K_2][K_3][K_4][K_5][K_6][K_7]) => T; +}) & { + map: (updater: (u: T[K][K_1][K_2][K_3][K_4][K_5][K_6]) => T[K][K_1][K_2][K_3][K_4][K_5][K_6]) => T; + set: (newU: T[K][K_1][K_2][K_3][K_4][K_5][K_6]) => T; +}) & { + map: (updater: (u: T[K][K_1][K_2][K_3][K_4][K_5]) => T[K][K_1][K_2][K_3][K_4][K_5]) => T; + set: (newU: T[K][K_1][K_2][K_3][K_4][K_5]) => T; +}) & { + map: (updater: (u: T[K][K_1][K_2][K_3][K_4]) => T[K][K_1][K_2][K_3][K_4]) => T; + set: (newU: T[K][K_1][K_2][K_3][K_4]) => T; +}) & { + map: (updater: (u: T[K][K_1][K_2][K_3]) => T[K][K_1][K_2][K_3]) => T; + set: (newU: T[K][K_1][K_2][K_3]) => T; +}) & { + map: (updater: (u: T[K][K_1][K_2]) => T[K][K_1][K_2]) => T; + set: (newU: T[K][K_1][K_2]) => T; +}) & { + map: (updater: (u: T[K][K_1]) => T[K][K_1]) => T; + set: (newU: T[K][K_1]) => T; +}) & { + map: (updater: (u: T[K]) => T[K]) => T; + set: (newU: T[K]) => T; +}) & { + map: (updater: (u: T) => T) => T; + set: (newU: T) => T; +}; +export declare const testRecFun: (parent: T) => { + result: T; + deeper: (child: U) => { + result: T & U; + deeper: (child: U_1) => { + result: T & U & U_1; + deeper: (child: U_2) => { + result: T & U & U_1 & U_2; + deeper: (child: U_3) => { + result: T & U & U_1 & U_2 & U_3; + deeper: (child: U_4) => { + result: T & U & U_1 & U_2 & U_3 & U_4; + deeper: (child: U_5) => { + result: T & U & U_1 & U_2 & U_3 & U_4 & U_5; + deeper: (child: U_6) => { + result: T & U & U_1 & U_2 & U_3 & U_4 & U_5 & U_6; + deeper: (child: U_7) => { + result: T & U & U_1 & U_2 & U_3 & U_4 & U_5 & U_6 & U_7; + deeper: (child: U_8) => { + result: T & U & U_1 & U_2 & U_3 & U_4 & U_5 & U_6 & U_7 & U_8; + deeper: (child: U_9) => { + result: T & U & U_1 & U_2 & U_3 & U_4 & U_5 & U_6 & U_7 & U_8 & U_9; + deeper: (child: U_10) => any; + }; + }; + }; + }; + }; + }; + }; + }; + }; + }; +}; diff --git a/tests/baselines/reference/declarationsWithRecursiveInternalTypesProduceUniqueTypeParams.symbols b/tests/baselines/reference/declarationsWithRecursiveInternalTypesProduceUniqueTypeParams.symbols new file mode 100644 index 00000000000..08c4eccca08 --- /dev/null +++ b/tests/baselines/reference/declarationsWithRecursiveInternalTypesProduceUniqueTypeParams.symbols @@ -0,0 +1,206 @@ +=== tests/cases/compiler/declarationsWithRecursiveInternalTypesProduceUniqueTypeParams.ts === +// Note that both of the following have an `any` in their return type from where we bottom out the type printout +// for having too many instances of the same symbol nesting. + +// Slightly simplified repro from https://github.com/microsoft/TypeScript/issues/30732 so it's easier to read and debug +export type Key = keyof U; +>Key : Symbol(Key, Decl(declarationsWithRecursiveInternalTypesProduceUniqueTypeParams.ts, 0, 0)) +>U : Symbol(U, Decl(declarationsWithRecursiveInternalTypesProduceUniqueTypeParams.ts, 4, 16)) +>U : Symbol(U, Decl(declarationsWithRecursiveInternalTypesProduceUniqueTypeParams.ts, 4, 16)) + +export type Value, U> = U[K]; +>Value : Symbol(Value, Decl(declarationsWithRecursiveInternalTypesProduceUniqueTypeParams.ts, 4, 29)) +>K : Symbol(K, Decl(declarationsWithRecursiveInternalTypesProduceUniqueTypeParams.ts, 5, 18)) +>Key : Symbol(Key, Decl(declarationsWithRecursiveInternalTypesProduceUniqueTypeParams.ts, 0, 0)) +>U : Symbol(U, Decl(declarationsWithRecursiveInternalTypesProduceUniqueTypeParams.ts, 5, 35)) +>U : Symbol(U, Decl(declarationsWithRecursiveInternalTypesProduceUniqueTypeParams.ts, 5, 35)) +>U : Symbol(U, Decl(declarationsWithRecursiveInternalTypesProduceUniqueTypeParams.ts, 5, 35)) +>K : Symbol(K, Decl(declarationsWithRecursiveInternalTypesProduceUniqueTypeParams.ts, 5, 18)) + +export const updateIfChanged = (t: T) => { +>updateIfChanged : Symbol(updateIfChanged, Decl(declarationsWithRecursiveInternalTypesProduceUniqueTypeParams.ts, 6, 12)) +>T : Symbol(T, Decl(declarationsWithRecursiveInternalTypesProduceUniqueTypeParams.ts, 6, 32)) +>t : Symbol(t, Decl(declarationsWithRecursiveInternalTypesProduceUniqueTypeParams.ts, 6, 35)) +>T : Symbol(T, Decl(declarationsWithRecursiveInternalTypesProduceUniqueTypeParams.ts, 6, 32)) + + const reduce = (u: U, update: (u: U) => T) => { +>reduce : Symbol(reduce, Decl(declarationsWithRecursiveInternalTypesProduceUniqueTypeParams.ts, 7, 9)) +>U : Symbol(U, Decl(declarationsWithRecursiveInternalTypesProduceUniqueTypeParams.ts, 7, 20)) +>u : Symbol(u, Decl(declarationsWithRecursiveInternalTypesProduceUniqueTypeParams.ts, 7, 23)) +>U : Symbol(U, Decl(declarationsWithRecursiveInternalTypesProduceUniqueTypeParams.ts, 7, 20)) +>update : Symbol(update, Decl(declarationsWithRecursiveInternalTypesProduceUniqueTypeParams.ts, 7, 28)) +>u : Symbol(u, Decl(declarationsWithRecursiveInternalTypesProduceUniqueTypeParams.ts, 7, 38)) +>U : Symbol(U, Decl(declarationsWithRecursiveInternalTypesProduceUniqueTypeParams.ts, 7, 20)) +>T : Symbol(T, Decl(declarationsWithRecursiveInternalTypesProduceUniqueTypeParams.ts, 6, 32)) + + const set = (newU: U) => Object.is(u, newU) ? t : update(newU); +>set : Symbol(set, Decl(declarationsWithRecursiveInternalTypesProduceUniqueTypeParams.ts, 8, 13)) +>newU : Symbol(newU, Decl(declarationsWithRecursiveInternalTypesProduceUniqueTypeParams.ts, 8, 21)) +>U : Symbol(U, Decl(declarationsWithRecursiveInternalTypesProduceUniqueTypeParams.ts, 7, 20)) +>Object.is : Symbol(ObjectConstructor.is, Decl(lib.es2015.core.d.ts, --, --)) +>Object : Symbol(Object, Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --)) +>is : Symbol(ObjectConstructor.is, Decl(lib.es2015.core.d.ts, --, --)) +>u : Symbol(u, Decl(declarationsWithRecursiveInternalTypesProduceUniqueTypeParams.ts, 7, 23)) +>newU : Symbol(newU, Decl(declarationsWithRecursiveInternalTypesProduceUniqueTypeParams.ts, 8, 21)) +>t : Symbol(t, Decl(declarationsWithRecursiveInternalTypesProduceUniqueTypeParams.ts, 6, 35)) +>update : Symbol(update, Decl(declarationsWithRecursiveInternalTypesProduceUniqueTypeParams.ts, 7, 28)) +>newU : Symbol(newU, Decl(declarationsWithRecursiveInternalTypesProduceUniqueTypeParams.ts, 8, 21)) + + return Object.assign( +>Object.assign : Symbol(ObjectConstructor.assign, Decl(lib.es2015.core.d.ts, --, --), Decl(lib.es2015.core.d.ts, --, --), Decl(lib.es2015.core.d.ts, --, --), Decl(lib.es2015.core.d.ts, --, --)) +>Object : Symbol(Object, Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --)) +>assign : Symbol(ObjectConstructor.assign, Decl(lib.es2015.core.d.ts, --, --), Decl(lib.es2015.core.d.ts, --, --), Decl(lib.es2015.core.d.ts, --, --), Decl(lib.es2015.core.d.ts, --, --)) + + >(key: K) => +>K : Symbol(K, Decl(declarationsWithRecursiveInternalTypesProduceUniqueTypeParams.ts, 10, 13)) +>Key : Symbol(Key, Decl(declarationsWithRecursiveInternalTypesProduceUniqueTypeParams.ts, 0, 0)) +>U : Symbol(U, Decl(declarationsWithRecursiveInternalTypesProduceUniqueTypeParams.ts, 7, 20)) +>key : Symbol(key, Decl(declarationsWithRecursiveInternalTypesProduceUniqueTypeParams.ts, 10, 31)) +>K : Symbol(K, Decl(declarationsWithRecursiveInternalTypesProduceUniqueTypeParams.ts, 10, 13)) + + reduce>(u[key as keyof U] as Value, (v: Value) => { +>reduce : Symbol(reduce, Decl(declarationsWithRecursiveInternalTypesProduceUniqueTypeParams.ts, 7, 9)) +>Value : Symbol(Value, Decl(declarationsWithRecursiveInternalTypesProduceUniqueTypeParams.ts, 4, 29)) +>K : Symbol(K, Decl(declarationsWithRecursiveInternalTypesProduceUniqueTypeParams.ts, 10, 13)) +>U : Symbol(U, Decl(declarationsWithRecursiveInternalTypesProduceUniqueTypeParams.ts, 7, 20)) +>u : Symbol(u, Decl(declarationsWithRecursiveInternalTypesProduceUniqueTypeParams.ts, 7, 23)) +>key : Symbol(key, Decl(declarationsWithRecursiveInternalTypesProduceUniqueTypeParams.ts, 10, 31)) +>U : Symbol(U, Decl(declarationsWithRecursiveInternalTypesProduceUniqueTypeParams.ts, 7, 20)) +>Value : Symbol(Value, Decl(declarationsWithRecursiveInternalTypesProduceUniqueTypeParams.ts, 4, 29)) +>K : Symbol(K, Decl(declarationsWithRecursiveInternalTypesProduceUniqueTypeParams.ts, 10, 13)) +>U : Symbol(U, Decl(declarationsWithRecursiveInternalTypesProduceUniqueTypeParams.ts, 7, 20)) +>v : Symbol(v, Decl(declarationsWithRecursiveInternalTypesProduceUniqueTypeParams.ts, 11, 71)) +>Value : Symbol(Value, Decl(declarationsWithRecursiveInternalTypesProduceUniqueTypeParams.ts, 4, 29)) +>K : Symbol(K, Decl(declarationsWithRecursiveInternalTypesProduceUniqueTypeParams.ts, 10, 13)) +>U : Symbol(U, Decl(declarationsWithRecursiveInternalTypesProduceUniqueTypeParams.ts, 7, 20)) + + return update(Object.assign(Array.isArray(u) ? [] : {}, u, { [key]: v })); +>update : Symbol(update, Decl(declarationsWithRecursiveInternalTypesProduceUniqueTypeParams.ts, 7, 28)) +>Object.assign : Symbol(ObjectConstructor.assign, Decl(lib.es2015.core.d.ts, --, --), Decl(lib.es2015.core.d.ts, --, --), Decl(lib.es2015.core.d.ts, --, --), Decl(lib.es2015.core.d.ts, --, --)) +>Object : Symbol(Object, Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --)) +>assign : Symbol(ObjectConstructor.assign, Decl(lib.es2015.core.d.ts, --, --), Decl(lib.es2015.core.d.ts, --, --), Decl(lib.es2015.core.d.ts, --, --), Decl(lib.es2015.core.d.ts, --, --)) +>Array.isArray : Symbol(ArrayConstructor.isArray, Decl(lib.es5.d.ts, --, --)) +>Array : Symbol(Array, Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --), Decl(lib.es2015.core.d.ts, --, --), Decl(lib.es2015.iterable.d.ts, --, --), Decl(lib.es2015.symbol.wellknown.d.ts, --, --)) +>isArray : Symbol(ArrayConstructor.isArray, Decl(lib.es5.d.ts, --, --)) +>u : Symbol(u, Decl(declarationsWithRecursiveInternalTypesProduceUniqueTypeParams.ts, 7, 23)) +>u : Symbol(u, Decl(declarationsWithRecursiveInternalTypesProduceUniqueTypeParams.ts, 7, 23)) +>[key] : Symbol([key], Decl(declarationsWithRecursiveInternalTypesProduceUniqueTypeParams.ts, 12, 80)) +>key : Symbol(key, Decl(declarationsWithRecursiveInternalTypesProduceUniqueTypeParams.ts, 10, 31)) +>v : Symbol(v, Decl(declarationsWithRecursiveInternalTypesProduceUniqueTypeParams.ts, 11, 71)) + + }), + { map: (updater: (u: U) => U) => set(updater(u)), set }); +>map : Symbol(map, Decl(declarationsWithRecursiveInternalTypesProduceUniqueTypeParams.ts, 14, 13)) +>updater : Symbol(updater, Decl(declarationsWithRecursiveInternalTypesProduceUniqueTypeParams.ts, 14, 20)) +>u : Symbol(u, Decl(declarationsWithRecursiveInternalTypesProduceUniqueTypeParams.ts, 14, 30)) +>U : Symbol(U, Decl(declarationsWithRecursiveInternalTypesProduceUniqueTypeParams.ts, 7, 20)) +>U : Symbol(U, Decl(declarationsWithRecursiveInternalTypesProduceUniqueTypeParams.ts, 7, 20)) +>set : Symbol(set, Decl(declarationsWithRecursiveInternalTypesProduceUniqueTypeParams.ts, 8, 13)) +>updater : Symbol(updater, Decl(declarationsWithRecursiveInternalTypesProduceUniqueTypeParams.ts, 14, 20)) +>u : Symbol(u, Decl(declarationsWithRecursiveInternalTypesProduceUniqueTypeParams.ts, 7, 23)) +>set : Symbol(set, Decl(declarationsWithRecursiveInternalTypesProduceUniqueTypeParams.ts, 14, 61)) + + }; + return reduce(t, (t: T) => t); +>reduce : Symbol(reduce, Decl(declarationsWithRecursiveInternalTypesProduceUniqueTypeParams.ts, 7, 9)) +>T : Symbol(T, Decl(declarationsWithRecursiveInternalTypesProduceUniqueTypeParams.ts, 6, 32)) +>t : Symbol(t, Decl(declarationsWithRecursiveInternalTypesProduceUniqueTypeParams.ts, 6, 35)) +>t : Symbol(t, Decl(declarationsWithRecursiveInternalTypesProduceUniqueTypeParams.ts, 16, 25)) +>T : Symbol(T, Decl(declarationsWithRecursiveInternalTypesProduceUniqueTypeParams.ts, 6, 32)) +>t : Symbol(t, Decl(declarationsWithRecursiveInternalTypesProduceUniqueTypeParams.ts, 16, 25)) + +}; + +// example from https://github.com/microsoft/TypeScript/issues/31605 + +export const testRecFun = (parent: T) => { +>testRecFun : Symbol(testRecFun, Decl(declarationsWithRecursiveInternalTypesProduceUniqueTypeParams.ts, 21, 12)) +>T : Symbol(T, Decl(declarationsWithRecursiveInternalTypesProduceUniqueTypeParams.ts, 21, 27)) +>Object : Symbol(Object, Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --)) +>parent : Symbol(parent, Decl(declarationsWithRecursiveInternalTypesProduceUniqueTypeParams.ts, 21, 45)) +>T : Symbol(T, Decl(declarationsWithRecursiveInternalTypesProduceUniqueTypeParams.ts, 21, 27)) + + return { + result: parent, +>result : Symbol(result, Decl(declarationsWithRecursiveInternalTypesProduceUniqueTypeParams.ts, 22, 12)) +>parent : Symbol(parent, Decl(declarationsWithRecursiveInternalTypesProduceUniqueTypeParams.ts, 21, 45)) + + deeper: (child: U) => +>deeper : Symbol(deeper, Decl(declarationsWithRecursiveInternalTypesProduceUniqueTypeParams.ts, 23, 23)) +>U : Symbol(U, Decl(declarationsWithRecursiveInternalTypesProduceUniqueTypeParams.ts, 24, 17)) +>Object : Symbol(Object, Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --)) +>child : Symbol(child, Decl(declarationsWithRecursiveInternalTypesProduceUniqueTypeParams.ts, 24, 35)) +>U : Symbol(U, Decl(declarationsWithRecursiveInternalTypesProduceUniqueTypeParams.ts, 24, 17)) + + testRecFun({ ...parent, ...child }) +>testRecFun : Symbol(testRecFun, Decl(declarationsWithRecursiveInternalTypesProduceUniqueTypeParams.ts, 21, 12)) +>T : Symbol(T, Decl(declarationsWithRecursiveInternalTypesProduceUniqueTypeParams.ts, 21, 27)) +>U : Symbol(U, Decl(declarationsWithRecursiveInternalTypesProduceUniqueTypeParams.ts, 24, 17)) +>parent : Symbol(parent, Decl(declarationsWithRecursiveInternalTypesProduceUniqueTypeParams.ts, 21, 45)) +>child : Symbol(child, Decl(declarationsWithRecursiveInternalTypesProduceUniqueTypeParams.ts, 24, 35)) + + }; +} + + +let p1 = testRecFun({ one: '1' }) +>p1 : Symbol(p1, Decl(declarationsWithRecursiveInternalTypesProduceUniqueTypeParams.ts, 30, 3)) +>testRecFun : Symbol(testRecFun, Decl(declarationsWithRecursiveInternalTypesProduceUniqueTypeParams.ts, 21, 12)) +>one : Symbol(one, Decl(declarationsWithRecursiveInternalTypesProduceUniqueTypeParams.ts, 30, 21)) + +void p1.result.one; +>p1.result.one : Symbol(one, Decl(declarationsWithRecursiveInternalTypesProduceUniqueTypeParams.ts, 30, 21)) +>p1.result : Symbol(result, Decl(declarationsWithRecursiveInternalTypesProduceUniqueTypeParams.ts, 22, 12)) +>p1 : Symbol(p1, Decl(declarationsWithRecursiveInternalTypesProduceUniqueTypeParams.ts, 30, 3)) +>result : Symbol(result, Decl(declarationsWithRecursiveInternalTypesProduceUniqueTypeParams.ts, 22, 12)) +>one : Symbol(one, Decl(declarationsWithRecursiveInternalTypesProduceUniqueTypeParams.ts, 30, 21)) + +let p2 = p1.deeper({ two: '2' }) +>p2 : Symbol(p2, Decl(declarationsWithRecursiveInternalTypesProduceUniqueTypeParams.ts, 32, 3)) +>p1.deeper : Symbol(deeper, Decl(declarationsWithRecursiveInternalTypesProduceUniqueTypeParams.ts, 23, 23)) +>p1 : Symbol(p1, Decl(declarationsWithRecursiveInternalTypesProduceUniqueTypeParams.ts, 30, 3)) +>deeper : Symbol(deeper, Decl(declarationsWithRecursiveInternalTypesProduceUniqueTypeParams.ts, 23, 23)) +>two : Symbol(two, Decl(declarationsWithRecursiveInternalTypesProduceUniqueTypeParams.ts, 32, 20)) + +void p2.result.one; +>p2.result.one : Symbol(one, Decl(declarationsWithRecursiveInternalTypesProduceUniqueTypeParams.ts, 30, 21)) +>p2.result : Symbol(result, Decl(declarationsWithRecursiveInternalTypesProduceUniqueTypeParams.ts, 22, 12)) +>p2 : Symbol(p2, Decl(declarationsWithRecursiveInternalTypesProduceUniqueTypeParams.ts, 32, 3)) +>result : Symbol(result, Decl(declarationsWithRecursiveInternalTypesProduceUniqueTypeParams.ts, 22, 12)) +>one : Symbol(one, Decl(declarationsWithRecursiveInternalTypesProduceUniqueTypeParams.ts, 30, 21)) + +void p2.result.two; +>p2.result.two : Symbol(two, Decl(declarationsWithRecursiveInternalTypesProduceUniqueTypeParams.ts, 32, 20)) +>p2.result : Symbol(result, Decl(declarationsWithRecursiveInternalTypesProduceUniqueTypeParams.ts, 22, 12)) +>p2 : Symbol(p2, Decl(declarationsWithRecursiveInternalTypesProduceUniqueTypeParams.ts, 32, 3)) +>result : Symbol(result, Decl(declarationsWithRecursiveInternalTypesProduceUniqueTypeParams.ts, 22, 12)) +>two : Symbol(two, Decl(declarationsWithRecursiveInternalTypesProduceUniqueTypeParams.ts, 32, 20)) + +let p3 = p2.deeper({ three: '3' }) +>p3 : Symbol(p3, Decl(declarationsWithRecursiveInternalTypesProduceUniqueTypeParams.ts, 35, 3)) +>p2.deeper : Symbol(deeper, Decl(declarationsWithRecursiveInternalTypesProduceUniqueTypeParams.ts, 23, 23)) +>p2 : Symbol(p2, Decl(declarationsWithRecursiveInternalTypesProduceUniqueTypeParams.ts, 32, 3)) +>deeper : Symbol(deeper, Decl(declarationsWithRecursiveInternalTypesProduceUniqueTypeParams.ts, 23, 23)) +>three : Symbol(three, Decl(declarationsWithRecursiveInternalTypesProduceUniqueTypeParams.ts, 35, 20)) + +void p3.result.one; +>p3.result.one : Symbol(one, Decl(declarationsWithRecursiveInternalTypesProduceUniqueTypeParams.ts, 30, 21)) +>p3.result : Symbol(result, Decl(declarationsWithRecursiveInternalTypesProduceUniqueTypeParams.ts, 22, 12)) +>p3 : Symbol(p3, Decl(declarationsWithRecursiveInternalTypesProduceUniqueTypeParams.ts, 35, 3)) +>result : Symbol(result, Decl(declarationsWithRecursiveInternalTypesProduceUniqueTypeParams.ts, 22, 12)) +>one : Symbol(one, Decl(declarationsWithRecursiveInternalTypesProduceUniqueTypeParams.ts, 30, 21)) + +void p3.result.two; +>p3.result.two : Symbol(two, Decl(declarationsWithRecursiveInternalTypesProduceUniqueTypeParams.ts, 32, 20)) +>p3.result : Symbol(result, Decl(declarationsWithRecursiveInternalTypesProduceUniqueTypeParams.ts, 22, 12)) +>p3 : Symbol(p3, Decl(declarationsWithRecursiveInternalTypesProduceUniqueTypeParams.ts, 35, 3)) +>result : Symbol(result, Decl(declarationsWithRecursiveInternalTypesProduceUniqueTypeParams.ts, 22, 12)) +>two : Symbol(two, Decl(declarationsWithRecursiveInternalTypesProduceUniqueTypeParams.ts, 32, 20)) + +void p3.result.three; +>p3.result.three : Symbol(three, Decl(declarationsWithRecursiveInternalTypesProduceUniqueTypeParams.ts, 35, 20)) +>p3.result : Symbol(result, Decl(declarationsWithRecursiveInternalTypesProduceUniqueTypeParams.ts, 22, 12)) +>p3 : Symbol(p3, Decl(declarationsWithRecursiveInternalTypesProduceUniqueTypeParams.ts, 35, 3)) +>result : Symbol(result, Decl(declarationsWithRecursiveInternalTypesProduceUniqueTypeParams.ts, 22, 12)) +>three : Symbol(three, Decl(declarationsWithRecursiveInternalTypesProduceUniqueTypeParams.ts, 35, 20)) + diff --git a/tests/baselines/reference/declarationsWithRecursiveInternalTypesProduceUniqueTypeParams.types b/tests/baselines/reference/declarationsWithRecursiveInternalTypesProduceUniqueTypeParams.types new file mode 100644 index 00000000000..68e2e12c65d --- /dev/null +++ b/tests/baselines/reference/declarationsWithRecursiveInternalTypesProduceUniqueTypeParams.types @@ -0,0 +1,212 @@ +=== tests/cases/compiler/declarationsWithRecursiveInternalTypesProduceUniqueTypeParams.ts === +// Note that both of the following have an `any` in their return type from where we bottom out the type printout +// for having too many instances of the same symbol nesting. + +// Slightly simplified repro from https://github.com/microsoft/TypeScript/issues/30732 so it's easier to read and debug +export type Key = keyof U; +>Key : keyof U + +export type Value, U> = U[K]; +>Value : U[K] + +export const updateIfChanged = (t: T) => { +>updateIfChanged : (t: T) => ((key: K) => ((key: K) => ((key: K) => ((key: K) => ((key: K) => ((key: K) => ((key: K) => ((key: K) => ((key: K) => ((key: K) => ((key: K) => any & { map: (updater: (u: T[K][K][K][K][K][K][K][K][K][K][K]) => T[K][K][K][K][K][K][K][K][K][K][K]) => T; set: (newU: T[K][K][K][K][K][K][K][K][K][K][K]) => T; }) & { map: (updater: (u: T[K][K][K][K][K][K][K][K][K][K]) => T[K][K][K][K][K][K][K][K][K][K]) => T; set: (newU: T[K][K][K][K][K][K][K][K][K][K]) => T; }) & { map: (updater: (u: T[K][K][K][K][K][K][K][K][K]) => T[K][K][K][K][K][K][K][K][K]) => T; set: (newU: T[K][K][K][K][K][K][K][K][K]) => T; }) & { map: (updater: (u: T[K][K][K][K][K][K][K][K]) => T[K][K][K][K][K][K][K][K]) => T; set: (newU: T[K][K][K][K][K][K][K][K]) => T; }) & { map: (updater: (u: T[K][K][K][K][K][K][K]) => T[K][K][K][K][K][K][K]) => T; set: (newU: T[K][K][K][K][K][K][K]) => T; }) & { map: (updater: (u: T[K][K][K][K][K][K]) => T[K][K][K][K][K][K]) => T; set: (newU: T[K][K][K][K][K][K]) => T; }) & { map: (updater: (u: T[K][K][K][K][K]) => T[K][K][K][K][K]) => T; set: (newU: T[K][K][K][K][K]) => T; }) & { map: (updater: (u: T[K][K][K][K]) => T[K][K][K][K]) => T; set: (newU: T[K][K][K][K]) => T; }) & { map: (updater: (u: T[K][K][K]) => T[K][K][K]) => T; set: (newU: T[K][K][K]) => T; }) & { map: (updater: (u: T[K][K]) => T[K][K]) => T; set: (newU: T[K][K]) => T; }) & { map: (updater: (u: T[K]) => T[K]) => T; set: (newU: T[K]) => T; }) & { map: (updater: (u: T) => T) => T; set: (newU: T) => T; } +>(t: T) => { const reduce = (u: U, update: (u: U) => T) => { const set = (newU: U) => Object.is(u, newU) ? t : update(newU); return Object.assign( >(key: K) => reduce>(u[key as keyof U] as Value, (v: Value) => { return update(Object.assign(Array.isArray(u) ? [] : {}, u, { [key]: v })); }), { map: (updater: (u: U) => U) => set(updater(u)), set }); }; return reduce(t, (t: T) => t);} : (t: T) => ((key: K) => ((key: K) => ((key: K) => ((key: K) => ((key: K) => ((key: K) => ((key: K) => ((key: K) => ((key: K) => ((key: K) => ((key: K) => any & { map: (updater: (u: T[K][K][K][K][K][K][K][K][K][K][K]) => T[K][K][K][K][K][K][K][K][K][K][K]) => T; set: (newU: T[K][K][K][K][K][K][K][K][K][K][K]) => T; }) & { map: (updater: (u: T[K][K][K][K][K][K][K][K][K][K]) => T[K][K][K][K][K][K][K][K][K][K]) => T; set: (newU: T[K][K][K][K][K][K][K][K][K][K]) => T; }) & { map: (updater: (u: T[K][K][K][K][K][K][K][K][K]) => T[K][K][K][K][K][K][K][K][K]) => T; set: (newU: T[K][K][K][K][K][K][K][K][K]) => T; }) & { map: (updater: (u: T[K][K][K][K][K][K][K][K]) => T[K][K][K][K][K][K][K][K]) => T; set: (newU: T[K][K][K][K][K][K][K][K]) => T; }) & { map: (updater: (u: T[K][K][K][K][K][K][K]) => T[K][K][K][K][K][K][K]) => T; set: (newU: T[K][K][K][K][K][K][K]) => T; }) & { map: (updater: (u: T[K][K][K][K][K][K]) => T[K][K][K][K][K][K]) => T; set: (newU: T[K][K][K][K][K][K]) => T; }) & { map: (updater: (u: T[K][K][K][K][K]) => T[K][K][K][K][K]) => T; set: (newU: T[K][K][K][K][K]) => T; }) & { map: (updater: (u: T[K][K][K][K]) => T[K][K][K][K]) => T; set: (newU: T[K][K][K][K]) => T; }) & { map: (updater: (u: T[K][K][K]) => T[K][K][K]) => T; set: (newU: T[K][K][K]) => T; }) & { map: (updater: (u: T[K][K]) => T[K][K]) => T; set: (newU: T[K][K]) => T; }) & { map: (updater: (u: T[K]) => T[K]) => T; set: (newU: T[K]) => T; }) & { map: (updater: (u: T) => T) => T; set: (newU: T) => T; } +>t : T + + const reduce = (u: U, update: (u: U) => T) => { +>reduce : (u: U, update: (u: U) => T) => ((key: K) => ((key: K) => ((key: K) => ((key: K) => ((key: K) => ((key: K) => ((key: K) => ((key: K) => ((key: K) => ((key: K) => ((key: K) => any & { map: (updater: (u: U[K][K][K][K][K][K][K][K][K][K][K]) => U[K][K][K][K][K][K][K][K][K][K][K]) => T; set: (newU: U[K][K][K][K][K][K][K][K][K][K][K]) => T; }) & { map: (updater: (u: U[K][K][K][K][K][K][K][K][K][K]) => U[K][K][K][K][K][K][K][K][K][K]) => T; set: (newU: U[K][K][K][K][K][K][K][K][K][K]) => T; }) & { map: (updater: (u: U[K][K][K][K][K][K][K][K][K]) => U[K][K][K][K][K][K][K][K][K]) => T; set: (newU: U[K][K][K][K][K][K][K][K][K]) => T; }) & { map: (updater: (u: U[K][K][K][K][K][K][K][K]) => U[K][K][K][K][K][K][K][K]) => T; set: (newU: U[K][K][K][K][K][K][K][K]) => T; }) & { map: (updater: (u: U[K][K][K][K][K][K][K]) => U[K][K][K][K][K][K][K]) => T; set: (newU: U[K][K][K][K][K][K][K]) => T; }) & { map: (updater: (u: U[K][K][K][K][K][K]) => U[K][K][K][K][K][K]) => T; set: (newU: U[K][K][K][K][K][K]) => T; }) & { map: (updater: (u: U[K][K][K][K][K]) => U[K][K][K][K][K]) => T; set: (newU: U[K][K][K][K][K]) => T; }) & { map: (updater: (u: U[K][K][K][K]) => U[K][K][K][K]) => T; set: (newU: U[K][K][K][K]) => T; }) & { map: (updater: (u: U[K][K][K]) => U[K][K][K]) => T; set: (newU: U[K][K][K]) => T; }) & { map: (updater: (u: U[K][K]) => U[K][K]) => T; set: (newU: U[K][K]) => T; }) & { map: (updater: (u: U[K]) => U[K]) => T; set: (newU: U[K]) => T; }) & { map: (updater: (u: U) => U) => T; set: (newU: U) => T; } +>(u: U, update: (u: U) => T) => { const set = (newU: U) => Object.is(u, newU) ? t : update(newU); return Object.assign( >(key: K) => reduce>(u[key as keyof U] as Value, (v: Value) => { return update(Object.assign(Array.isArray(u) ? [] : {}, u, { [key]: v })); }), { map: (updater: (u: U) => U) => set(updater(u)), set }); } : (u: U, update: (u: U) => T) => ((key: K) => ((key: K) => ((key: K) => ((key: K) => ((key: K) => ((key: K) => ((key: K) => ((key: K) => ((key: K) => ((key: K) => ((key: K) => any & { map: (updater: (u: U[K][K][K][K][K][K][K][K][K][K][K]) => U[K][K][K][K][K][K][K][K][K][K][K]) => T; set: (newU: U[K][K][K][K][K][K][K][K][K][K][K]) => T; }) & { map: (updater: (u: U[K][K][K][K][K][K][K][K][K][K]) => U[K][K][K][K][K][K][K][K][K][K]) => T; set: (newU: U[K][K][K][K][K][K][K][K][K][K]) => T; }) & { map: (updater: (u: U[K][K][K][K][K][K][K][K][K]) => U[K][K][K][K][K][K][K][K][K]) => T; set: (newU: U[K][K][K][K][K][K][K][K][K]) => T; }) & { map: (updater: (u: U[K][K][K][K][K][K][K][K]) => U[K][K][K][K][K][K][K][K]) => T; set: (newU: U[K][K][K][K][K][K][K][K]) => T; }) & { map: (updater: (u: U[K][K][K][K][K][K][K]) => U[K][K][K][K][K][K][K]) => T; set: (newU: U[K][K][K][K][K][K][K]) => T; }) & { map: (updater: (u: U[K][K][K][K][K][K]) => U[K][K][K][K][K][K]) => T; set: (newU: U[K][K][K][K][K][K]) => T; }) & { map: (updater: (u: U[K][K][K][K][K]) => U[K][K][K][K][K]) => T; set: (newU: U[K][K][K][K][K]) => T; }) & { map: (updater: (u: U[K][K][K][K]) => U[K][K][K][K]) => T; set: (newU: U[K][K][K][K]) => T; }) & { map: (updater: (u: U[K][K][K]) => U[K][K][K]) => T; set: (newU: U[K][K][K]) => T; }) & { map: (updater: (u: U[K][K]) => U[K][K]) => T; set: (newU: U[K][K]) => T; }) & { map: (updater: (u: U[K]) => U[K]) => T; set: (newU: U[K]) => T; }) & { map: (updater: (u: U) => U) => T; set: (newU: U) => T; } +>u : U +>update : (u: U) => T +>u : U + + const set = (newU: U) => Object.is(u, newU) ? t : update(newU); +>set : (newU: U) => T +>(newU: U) => Object.is(u, newU) ? t : update(newU) : (newU: U) => T +>newU : U +>Object.is(u, newU) ? t : update(newU) : T +>Object.is(u, newU) : boolean +>Object.is : (value1: any, value2: any) => boolean +>Object : ObjectConstructor +>is : (value1: any, value2: any) => boolean +>u : U +>newU : U +>t : T +>update(newU) : T +>update : (u: U) => T +>newU : U + + return Object.assign( +>Object.assign( >(key: K) => reduce>(u[key as keyof U] as Value, (v: Value) => { return update(Object.assign(Array.isArray(u) ? [] : {}, u, { [key]: v })); }), { map: (updater: (u: U) => U) => set(updater(u)), set }) : ((key: K) => ((key: K) => ((key: K) => ((key: K) => ((key: K) => ((key: K) => ((key: K) => ((key: K) => ((key: K) => ((key: K) => ((key: K) => any & { map: (updater: (u: U[K][K][K][K][K][K][K][K][K][K][K]) => U[K][K][K][K][K][K][K][K][K][K][K]) => T; set: (newU: U[K][K][K][K][K][K][K][K][K][K][K]) => T; }) & { map: (updater: (u: U[K][K][K][K][K][K][K][K][K][K]) => U[K][K][K][K][K][K][K][K][K][K]) => T; set: (newU: U[K][K][K][K][K][K][K][K][K][K]) => T; }) & { map: (updater: (u: U[K][K][K][K][K][K][K][K][K]) => U[K][K][K][K][K][K][K][K][K]) => T; set: (newU: U[K][K][K][K][K][K][K][K][K]) => T; }) & { map: (updater: (u: U[K][K][K][K][K][K][K][K]) => U[K][K][K][K][K][K][K][K]) => T; set: (newU: U[K][K][K][K][K][K][K][K]) => T; }) & { map: (updater: (u: U[K][K][K][K][K][K][K]) => U[K][K][K][K][K][K][K]) => T; set: (newU: U[K][K][K][K][K][K][K]) => T; }) & { map: (updater: (u: U[K][K][K][K][K][K]) => U[K][K][K][K][K][K]) => T; set: (newU: U[K][K][K][K][K][K]) => T; }) & { map: (updater: (u: U[K][K][K][K][K]) => U[K][K][K][K][K]) => T; set: (newU: U[K][K][K][K][K]) => T; }) & { map: (updater: (u: U[K][K][K][K]) => U[K][K][K][K]) => T; set: (newU: U[K][K][K][K]) => T; }) & { map: (updater: (u: U[K][K][K]) => U[K][K][K]) => T; set: (newU: U[K][K][K]) => T; }) & { map: (updater: (u: U[K][K]) => U[K][K]) => T; set: (newU: U[K][K]) => T; }) & { map: (updater: (u: U[K]) => U[K]) => T; set: (newU: U[K]) => T; }) & { map: (updater: (u: U) => U) => T; set: (newU: U) => T; } +>Object.assign : { (target: T, source: U): T & U; (target: T, source1: U, source2: V): T & U & V; (target: T, source1: U, source2: V, source3: W): T & U & V & W; (target: object, ...sources: any[]): any; } +>Object : ObjectConstructor +>assign : { (target: T, source: U): T & U; (target: T, source1: U, source2: V): T & U & V; (target: T, source1: U, source2: V, source3: W): T & U & V & W; (target: object, ...sources: any[]): any; } + + >(key: K) => +>>(key: K) => reduce>(u[key as keyof U] as Value, (v: Value) => { return update(Object.assign(Array.isArray(u) ? [] : {}, u, { [key]: v })); }) : (key: K) => ((key: K) => ((key: K) => ((key: K) => ((key: K) => ((key: K) => ((key: K) => ((key: K) => ((key: K) => ((key: K) => ((key: K) => any & { map: (updater: (u: U[K][K][K][K][K][K][K][K][K][K][K]) => U[K][K][K][K][K][K][K][K][K][K][K]) => T; set: (newU: U[K][K][K][K][K][K][K][K][K][K][K]) => T; }) & { map: (updater: (u: U[K][K][K][K][K][K][K][K][K][K]) => U[K][K][K][K][K][K][K][K][K][K]) => T; set: (newU: U[K][K][K][K][K][K][K][K][K][K]) => T; }) & { map: (updater: (u: U[K][K][K][K][K][K][K][K][K]) => U[K][K][K][K][K][K][K][K][K]) => T; set: (newU: U[K][K][K][K][K][K][K][K][K]) => T; }) & { map: (updater: (u: U[K][K][K][K][K][K][K][K]) => U[K][K][K][K][K][K][K][K]) => T; set: (newU: U[K][K][K][K][K][K][K][K]) => T; }) & { map: (updater: (u: U[K][K][K][K][K][K][K]) => U[K][K][K][K][K][K][K]) => T; set: (newU: U[K][K][K][K][K][K][K]) => T; }) & { map: (updater: (u: U[K][K][K][K][K][K]) => U[K][K][K][K][K][K]) => T; set: (newU: U[K][K][K][K][K][K]) => T; }) & { map: (updater: (u: U[K][K][K][K][K]) => U[K][K][K][K][K]) => T; set: (newU: U[K][K][K][K][K]) => T; }) & { map: (updater: (u: U[K][K][K][K]) => U[K][K][K][K]) => T; set: (newU: U[K][K][K][K]) => T; }) & { map: (updater: (u: U[K][K][K]) => U[K][K][K]) => T; set: (newU: U[K][K][K]) => T; }) & { map: (updater: (u: U[K][K]) => U[K][K]) => T; set: (newU: U[K][K]) => T; }) & { map: (updater: (u: U[K]) => U[K]) => T; set: (newU: U[K]) => T; } +>key : K + + reduce>(u[key as keyof U] as Value, (v: Value) => { +>reduce>(u[key as keyof U] as Value, (v: Value) => { return update(Object.assign(Array.isArray(u) ? [] : {}, u, { [key]: v })); }) : ((key: K) => ((key: K) => ((key: K) => ((key: K) => ((key: K) => ((key: K) => ((key: K) => ((key: K) => ((key: K) => ((key: K) => ((key: K) => any & { map: (updater: (u: U[K][K][K][K][K][K][K][K][K][K][K][K]) => U[K][K][K][K][K][K][K][K][K][K][K][K]) => T; set: (newU: U[K][K][K][K][K][K][K][K][K][K][K][K]) => T; }) & { map: (updater: (u: U[K][K][K][K][K][K][K][K][K][K][K]) => U[K][K][K][K][K][K][K][K][K][K][K]) => T; set: (newU: U[K][K][K][K][K][K][K][K][K][K][K]) => T; }) & { map: (updater: (u: U[K][K][K][K][K][K][K][K][K][K]) => U[K][K][K][K][K][K][K][K][K][K]) => T; set: (newU: U[K][K][K][K][K][K][K][K][K][K]) => T; }) & { map: (updater: (u: U[K][K][K][K][K][K][K][K][K]) => U[K][K][K][K][K][K][K][K][K]) => T; set: (newU: U[K][K][K][K][K][K][K][K][K]) => T; }) & { map: (updater: (u: U[K][K][K][K][K][K][K][K]) => U[K][K][K][K][K][K][K][K]) => T; set: (newU: U[K][K][K][K][K][K][K][K]) => T; }) & { map: (updater: (u: U[K][K][K][K][K][K][K]) => U[K][K][K][K][K][K][K]) => T; set: (newU: U[K][K][K][K][K][K][K]) => T; }) & { map: (updater: (u: U[K][K][K][K][K][K]) => U[K][K][K][K][K][K]) => T; set: (newU: U[K][K][K][K][K][K]) => T; }) & { map: (updater: (u: U[K][K][K][K][K]) => U[K][K][K][K][K]) => T; set: (newU: U[K][K][K][K][K]) => T; }) & { map: (updater: (u: U[K][K][K][K]) => U[K][K][K][K]) => T; set: (newU: U[K][K][K][K]) => T; }) & { map: (updater: (u: U[K][K][K]) => U[K][K][K]) => T; set: (newU: U[K][K][K]) => T; }) & { map: (updater: (u: U[K][K]) => U[K][K]) => T; set: (newU: U[K][K]) => T; }) & { map: (updater: (u: U[K]) => U[K]) => T; set: (newU: U[K]) => T; } +>reduce : (u: U, update: (u: U) => T) => ((key: K) => ((key: K) => ((key: K) => ((key: K) => ((key: K) => ((key: K) => ((key: K) => ((key: K) => ((key: K) => ((key: K) => ((key: K) => any & { map: (updater: (u: U[K][K][K][K][K][K][K][K][K][K][K]) => U[K][K][K][K][K][K][K][K][K][K][K]) => T; set: (newU: U[K][K][K][K][K][K][K][K][K][K][K]) => T; }) & { map: (updater: (u: U[K][K][K][K][K][K][K][K][K][K]) => U[K][K][K][K][K][K][K][K][K][K]) => T; set: (newU: U[K][K][K][K][K][K][K][K][K][K]) => T; }) & { map: (updater: (u: U[K][K][K][K][K][K][K][K][K]) => U[K][K][K][K][K][K][K][K][K]) => T; set: (newU: U[K][K][K][K][K][K][K][K][K]) => T; }) & { map: (updater: (u: U[K][K][K][K][K][K][K][K]) => U[K][K][K][K][K][K][K][K]) => T; set: (newU: U[K][K][K][K][K][K][K][K]) => T; }) & { map: (updater: (u: U[K][K][K][K][K][K][K]) => U[K][K][K][K][K][K][K]) => T; set: (newU: U[K][K][K][K][K][K][K]) => T; }) & { map: (updater: (u: U[K][K][K][K][K][K]) => U[K][K][K][K][K][K]) => T; set: (newU: U[K][K][K][K][K][K]) => T; }) & { map: (updater: (u: U[K][K][K][K][K]) => U[K][K][K][K][K]) => T; set: (newU: U[K][K][K][K][K]) => T; }) & { map: (updater: (u: U[K][K][K][K]) => U[K][K][K][K]) => T; set: (newU: U[K][K][K][K]) => T; }) & { map: (updater: (u: U[K][K][K]) => U[K][K][K]) => T; set: (newU: U[K][K][K]) => T; }) & { map: (updater: (u: U[K][K]) => U[K][K]) => T; set: (newU: U[K][K]) => T; }) & { map: (updater: (u: U[K]) => U[K]) => T; set: (newU: U[K]) => T; }) & { map: (updater: (u: U) => U) => T; set: (newU: U) => T; } +>u[key as keyof U] as Value : U[K] +>u[key as keyof U] : U[keyof U] +>u : U +>key as keyof U : keyof U +>key : K +>(v: Value) => { return update(Object.assign(Array.isArray(u) ? [] : {}, u, { [key]: v })); } : (v: U[K]) => T +>v : U[K] + + return update(Object.assign(Array.isArray(u) ? [] : {}, u, { [key]: v })); +>update(Object.assign(Array.isArray(u) ? [] : {}, u, { [key]: v })) : T +>update : (u: U) => T +>Object.assign(Array.isArray(u) ? [] : {}, u, { [key]: v }) : U & { [x: string]: U[K]; } +>Object.assign : { (target: T, source: U): T & U; (target: T, source1: U, source2: V): T & U & V; (target: T, source1: U, source2: V, source3: W): T & U & V & W; (target: object, ...sources: any[]): any; } +>Object : ObjectConstructor +>assign : { (target: T, source: U): T & U; (target: T, source1: U, source2: V): T & U & V; (target: T, source1: U, source2: V, source3: W): T & U & V & W; (target: object, ...sources: any[]): any; } +>Array.isArray(u) ? [] : {} : undefined[] | {} +>Array.isArray(u) : boolean +>Array.isArray : (arg: any) => arg is any[] +>Array : ArrayConstructor +>isArray : (arg: any) => arg is any[] +>u : U +>[] : undefined[] +>{} : {} +>u : U +>{ [key]: v } : { [x: string]: U[K]; } +>[key] : U[K] +>key : K +>v : U[K] + + }), + { map: (updater: (u: U) => U) => set(updater(u)), set }); +>{ map: (updater: (u: U) => U) => set(updater(u)), set } : { map: (updater: (u: U) => U) => T; set: (newU: U) => T; } +>map : (updater: (u: U) => U) => T +>(updater: (u: U) => U) => set(updater(u)) : (updater: (u: U) => U) => T +>updater : (u: U) => U +>u : U +>set(updater(u)) : T +>set : (newU: U) => T +>updater(u) : U +>updater : (u: U) => U +>u : U +>set : (newU: U) => T + + }; + return reduce(t, (t: T) => t); +>reduce(t, (t: T) => t) : ((key: K) => ((key: K) => ((key: K) => ((key: K) => ((key: K) => ((key: K) => ((key: K) => ((key: K) => ((key: K) => ((key: K) => ((key: K) => any & { map: (updater: (u: T[K][K][K][K][K][K][K][K][K][K][K]) => T[K][K][K][K][K][K][K][K][K][K][K]) => T; set: (newU: T[K][K][K][K][K][K][K][K][K][K][K]) => T; }) & { map: (updater: (u: T[K][K][K][K][K][K][K][K][K][K]) => T[K][K][K][K][K][K][K][K][K][K]) => T; set: (newU: T[K][K][K][K][K][K][K][K][K][K]) => T; }) & { map: (updater: (u: T[K][K][K][K][K][K][K][K][K]) => T[K][K][K][K][K][K][K][K][K]) => T; set: (newU: T[K][K][K][K][K][K][K][K][K]) => T; }) & { map: (updater: (u: T[K][K][K][K][K][K][K][K]) => T[K][K][K][K][K][K][K][K]) => T; set: (newU: T[K][K][K][K][K][K][K][K]) => T; }) & { map: (updater: (u: T[K][K][K][K][K][K][K]) => T[K][K][K][K][K][K][K]) => T; set: (newU: T[K][K][K][K][K][K][K]) => T; }) & { map: (updater: (u: T[K][K][K][K][K][K]) => T[K][K][K][K][K][K]) => T; set: (newU: T[K][K][K][K][K][K]) => T; }) & { map: (updater: (u: T[K][K][K][K][K]) => T[K][K][K][K][K]) => T; set: (newU: T[K][K][K][K][K]) => T; }) & { map: (updater: (u: T[K][K][K][K]) => T[K][K][K][K]) => T; set: (newU: T[K][K][K][K]) => T; }) & { map: (updater: (u: T[K][K][K]) => T[K][K][K]) => T; set: (newU: T[K][K][K]) => T; }) & { map: (updater: (u: T[K][K]) => T[K][K]) => T; set: (newU: T[K][K]) => T; }) & { map: (updater: (u: T[K]) => T[K]) => T; set: (newU: T[K]) => T; }) & { map: (updater: (u: T) => T) => T; set: (newU: T) => T; } +>reduce : (u: U, update: (u: U) => T) => ((key: K) => ((key: K) => ((key: K) => ((key: K) => ((key: K) => ((key: K) => ((key: K) => ((key: K) => ((key: K) => ((key: K) => ((key: K) => any & { map: (updater: (u: U[K][K][K][K][K][K][K][K][K][K][K]) => U[K][K][K][K][K][K][K][K][K][K][K]) => T; set: (newU: U[K][K][K][K][K][K][K][K][K][K][K]) => T; }) & { map: (updater: (u: U[K][K][K][K][K][K][K][K][K][K]) => U[K][K][K][K][K][K][K][K][K][K]) => T; set: (newU: U[K][K][K][K][K][K][K][K][K][K]) => T; }) & { map: (updater: (u: U[K][K][K][K][K][K][K][K][K]) => U[K][K][K][K][K][K][K][K][K]) => T; set: (newU: U[K][K][K][K][K][K][K][K][K]) => T; }) & { map: (updater: (u: U[K][K][K][K][K][K][K][K]) => U[K][K][K][K][K][K][K][K]) => T; set: (newU: U[K][K][K][K][K][K][K][K]) => T; }) & { map: (updater: (u: U[K][K][K][K][K][K][K]) => U[K][K][K][K][K][K][K]) => T; set: (newU: U[K][K][K][K][K][K][K]) => T; }) & { map: (updater: (u: U[K][K][K][K][K][K]) => U[K][K][K][K][K][K]) => T; set: (newU: U[K][K][K][K][K][K]) => T; }) & { map: (updater: (u: U[K][K][K][K][K]) => U[K][K][K][K][K]) => T; set: (newU: U[K][K][K][K][K]) => T; }) & { map: (updater: (u: U[K][K][K][K]) => U[K][K][K][K]) => T; set: (newU: U[K][K][K][K]) => T; }) & { map: (updater: (u: U[K][K][K]) => U[K][K][K]) => T; set: (newU: U[K][K][K]) => T; }) & { map: (updater: (u: U[K][K]) => U[K][K]) => T; set: (newU: U[K][K]) => T; }) & { map: (updater: (u: U[K]) => U[K]) => T; set: (newU: U[K]) => T; }) & { map: (updater: (u: U) => U) => T; set: (newU: U) => T; } +>t : T +>(t: T) => t : (t: T) => T +>t : T +>t : T + +}; + +// example from https://github.com/microsoft/TypeScript/issues/31605 + +export const testRecFun = (parent: T) => { +>testRecFun : (parent: T) => { result: T; deeper: (child: U) => { result: T & U; deeper: (child: U) => { result: T & U & U; deeper: (child: U) => { result: T & U & U & U; deeper: (child: U) => { result: T & U & U & U & U; deeper: (child: U) => { result: T & U & U & U & U & U; deeper: (child: U) => { result: T & U & U & U & U & U & U; deeper: (child: U) => { result: T & U & U & U & U & U & U & U; deeper: (child: U) => { result: T & U & U & U & U & U & U & U & U; deeper: (child: U) => { result: T & U & U & U & U & U & U & U & U & U; deeper: (child: U) => { result: T & U & U & U & U & U & U & U & U & U & U; deeper: (child: U) => any; }; }; }; }; }; }; }; }; }; }; } +>(parent: T) => { return { result: parent, deeper: (child: U) => testRecFun({ ...parent, ...child }) };} : (parent: T) => { result: T; deeper: (child: U) => { result: T & U; deeper: (child: U) => { result: T & U & U; deeper: (child: U) => { result: T & U & U & U; deeper: (child: U) => { result: T & U & U & U & U; deeper: (child: U) => { result: T & U & U & U & U & U; deeper: (child: U) => { result: T & U & U & U & U & U & U; deeper: (child: U) => { result: T & U & U & U & U & U & U & U; deeper: (child: U) => { result: T & U & U & U & U & U & U & U & U; deeper: (child: U) => { result: T & U & U & U & U & U & U & U & U & U; deeper: (child: U) => { result: T & U & U & U & U & U & U & U & U & U & U; deeper: (child: U) => any; }; }; }; }; }; }; }; }; }; }; } +>parent : T + + return { +>{ result: parent, deeper: (child: U) => testRecFun({ ...parent, ...child }) } : { result: T; deeper: (child: U) => { result: T & U; deeper: (child: U) => { result: T & U & U; deeper: (child: U) => { result: T & U & U & U; deeper: (child: U) => { result: T & U & U & U & U; deeper: (child: U) => { result: T & U & U & U & U & U; deeper: (child: U) => { result: T & U & U & U & U & U & U; deeper: (child: U) => { result: T & U & U & U & U & U & U & U; deeper: (child: U) => { result: T & U & U & U & U & U & U & U & U; deeper: (child: U) => { result: T & U & U & U & U & U & U & U & U & U; deeper: (child: U) => { result: T & U & U & U & U & U & U & U & U & U & U; deeper: (child: U) => any; }; }; }; }; }; }; }; }; }; }; } + + result: parent, +>result : T +>parent : T + + deeper: (child: U) => +>deeper : (child: U) => { result: T & U; deeper: (child: U) => { result: T & U & U; deeper: (child: U) => { result: T & U & U & U; deeper: (child: U) => { result: T & U & U & U & U; deeper: (child: U) => { result: T & U & U & U & U & U; deeper: (child: U) => { result: T & U & U & U & U & U & U; deeper: (child: U) => { result: T & U & U & U & U & U & U & U; deeper: (child: U) => { result: T & U & U & U & U & U & U & U & U; deeper: (child: U) => { result: T & U & U & U & U & U & U & U & U & U; deeper: (child: U) => { result: T & U & U & U & U & U & U & U & U & U & U; deeper: (child: U) => { result: T & U & U & U & U & U & U & U & U & U & U & U; deeper: any; }; }; }; }; }; }; }; }; }; }; } +>(child: U) => testRecFun({ ...parent, ...child }) : (child: U) => { result: T & U; deeper: (child: U) => { result: T & U & U; deeper: (child: U) => { result: T & U & U & U; deeper: (child: U) => { result: T & U & U & U & U; deeper: (child: U) => { result: T & U & U & U & U & U; deeper: (child: U) => { result: T & U & U & U & U & U & U; deeper: (child: U) => { result: T & U & U & U & U & U & U & U; deeper: (child: U) => { result: T & U & U & U & U & U & U & U & U; deeper: (child: U) => { result: T & U & U & U & U & U & U & U & U & U; deeper: (child: U) => { result: T & U & U & U & U & U & U & U & U & U & U; deeper: (child: U) => { result: T & U & U & U & U & U & U & U & U & U & U & U; deeper: any; }; }; }; }; }; }; }; }; }; }; } +>child : U + + testRecFun({ ...parent, ...child }) +>testRecFun({ ...parent, ...child }) : { result: T & U; deeper: (child: U) => { result: T & U & U; deeper: (child: U) => { result: T & U & U & U; deeper: (child: U) => { result: T & U & U & U & U; deeper: (child: U) => { result: T & U & U & U & U & U; deeper: (child: U) => { result: T & U & U & U & U & U & U; deeper: (child: U) => { result: T & U & U & U & U & U & U & U; deeper: (child: U) => { result: T & U & U & U & U & U & U & U & U; deeper: (child: U) => { result: T & U & U & U & U & U & U & U & U & U; deeper: (child: U) => { result: T & U & U & U & U & U & U & U & U & U & U; deeper: (child: U) => { result: T & U & U & U & U & U & U & U & U & U & U & U; deeper: (child: U) => any; }; }; }; }; }; }; }; }; }; }; } +>testRecFun : (parent: T) => { result: T; deeper: (child: U) => { result: T & U; deeper: (child: U) => { result: T & U & U; deeper: (child: U) => { result: T & U & U & U; deeper: (child: U) => { result: T & U & U & U & U; deeper: (child: U) => { result: T & U & U & U & U & U; deeper: (child: U) => { result: T & U & U & U & U & U & U; deeper: (child: U) => { result: T & U & U & U & U & U & U & U; deeper: (child: U) => { result: T & U & U & U & U & U & U & U & U; deeper: (child: U) => { result: T & U & U & U & U & U & U & U & U & U; deeper: (child: U) => { result: T & U & U & U & U & U & U & U & U & U & U; deeper: (child: U) => any; }; }; }; }; }; }; }; }; }; }; } +>{ ...parent, ...child } : T & U +>parent : T +>child : U + + }; +} + + +let p1 = testRecFun({ one: '1' }) +>p1 : { result: { one: string; }; deeper: (child: U) => { result: { one: string; } & U; deeper: (child: U) => { result: { one: string; } & U & U; deeper: (child: U) => { result: { one: string; } & U & U & U; deeper: (child: U) => { result: { one: string; } & U & U & U & U; deeper: (child: U) => { result: { one: string; } & U & U & U & U & U; deeper: (child: U) => { result: { one: string; } & U & U & U & U & U & U; deeper: (child: U) => { result: { one: string; } & U & U & U & U & U & U & U; deeper: (child: U) => { result: { one: string; } & U & U & U & U & U & U & U & U; deeper: (child: U) => { result: { one: string; } & U & U & U & U & U & U & U & U & U; deeper: (child: U) => { result: { one: string; } & U & U & U & U & U & U & U & U & U & U; deeper: (child: U) => any; }; }; }; }; }; }; }; }; }; }; } +>testRecFun({ one: '1' }) : { result: { one: string; }; deeper: (child: U) => { result: { one: string; } & U; deeper: (child: U) => { result: { one: string; } & U & U; deeper: (child: U) => { result: { one: string; } & U & U & U; deeper: (child: U) => { result: { one: string; } & U & U & U & U; deeper: (child: U) => { result: { one: string; } & U & U & U & U & U; deeper: (child: U) => { result: { one: string; } & U & U & U & U & U & U; deeper: (child: U) => { result: { one: string; } & U & U & U & U & U & U & U; deeper: (child: U) => { result: { one: string; } & U & U & U & U & U & U & U & U; deeper: (child: U) => { result: { one: string; } & U & U & U & U & U & U & U & U & U; deeper: (child: U) => { result: { one: string; } & U & U & U & U & U & U & U & U & U & U; deeper: (child: U) => any; }; }; }; }; }; }; }; }; }; }; } +>testRecFun : (parent: T) => { result: T; deeper: (child: U) => { result: T & U; deeper: (child: U) => { result: T & U & U; deeper: (child: U) => { result: T & U & U & U; deeper: (child: U) => { result: T & U & U & U & U; deeper: (child: U) => { result: T & U & U & U & U & U; deeper: (child: U) => { result: T & U & U & U & U & U & U; deeper: (child: U) => { result: T & U & U & U & U & U & U & U; deeper: (child: U) => { result: T & U & U & U & U & U & U & U & U; deeper: (child: U) => { result: T & U & U & U & U & U & U & U & U & U; deeper: (child: U) => { result: T & U & U & U & U & U & U & U & U & U & U; deeper: (child: U) => any; }; }; }; }; }; }; }; }; }; }; } +>{ one: '1' } : { one: string; } +>one : string +>'1' : "1" + +void p1.result.one; +>void p1.result.one : undefined +>p1.result.one : string +>p1.result : { one: string; } +>p1 : { result: { one: string; }; deeper: (child: U) => { result: { one: string; } & U; deeper: (child: U) => { result: { one: string; } & U & U; deeper: (child: U) => { result: { one: string; } & U & U & U; deeper: (child: U) => { result: { one: string; } & U & U & U & U; deeper: (child: U) => { result: { one: string; } & U & U & U & U & U; deeper: (child: U) => { result: { one: string; } & U & U & U & U & U & U; deeper: (child: U) => { result: { one: string; } & U & U & U & U & U & U & U; deeper: (child: U) => { result: { one: string; } & U & U & U & U & U & U & U & U; deeper: (child: U) => { result: { one: string; } & U & U & U & U & U & U & U & U & U; deeper: (child: U) => { result: { one: string; } & U & U & U & U & U & U & U & U & U & U; deeper: (child: U) => any; }; }; }; }; }; }; }; }; }; }; } +>result : { one: string; } +>one : string + +let p2 = p1.deeper({ two: '2' }) +>p2 : { result: { one: string; } & { two: string; }; deeper: (child: U) => { result: { one: string; } & { two: string; } & U; deeper: (child: U) => { result: { one: string; } & { two: string; } & U & U; deeper: (child: U) => { result: { one: string; } & { two: string; } & U & U & U; deeper: (child: U) => { result: { one: string; } & { two: string; } & U & U & U & U; deeper: (child: U) => { result: { one: string; } & { two: string; } & U & U & U & U & U; deeper: (child: U) => { result: { one: string; } & { two: string; } & U & U & U & U & U & U; deeper: (child: U) => { result: { one: string; } & { two: string; } & U & U & U & U & U & U & U; deeper: (child: U) => { result: { one: string; } & { two: string; } & U & U & U & U & U & U & U & U; deeper: (child: U) => { result: { one: string; } & { two: string; } & U & U & U & U & U & U & U & U & U; deeper: (child: U) => { result: { one: string; } & { two: string; } & U & U & U & U & U & U & U & U & U & U; deeper: (child: U) => any; }; }; }; }; }; }; }; }; }; }; } +>p1.deeper({ two: '2' }) : { result: { one: string; } & { two: string; }; deeper: (child: U) => { result: { one: string; } & { two: string; } & U; deeper: (child: U) => { result: { one: string; } & { two: string; } & U & U; deeper: (child: U) => { result: { one: string; } & { two: string; } & U & U & U; deeper: (child: U) => { result: { one: string; } & { two: string; } & U & U & U & U; deeper: (child: U) => { result: { one: string; } & { two: string; } & U & U & U & U & U; deeper: (child: U) => { result: { one: string; } & { two: string; } & U & U & U & U & U & U; deeper: (child: U) => { result: { one: string; } & { two: string; } & U & U & U & U & U & U & U; deeper: (child: U) => { result: { one: string; } & { two: string; } & U & U & U & U & U & U & U & U; deeper: (child: U) => { result: { one: string; } & { two: string; } & U & U & U & U & U & U & U & U & U; deeper: (child: U) => { result: { one: string; } & { two: string; } & U & U & U & U & U & U & U & U & U & U; deeper: (child: U) => any; }; }; }; }; }; }; }; }; }; }; } +>p1.deeper : (child: U) => { result: { one: string; } & U; deeper: (child: U) => { result: { one: string; } & U & U; deeper: (child: U) => { result: { one: string; } & U & U & U; deeper: (child: U) => { result: { one: string; } & U & U & U & U; deeper: (child: U) => { result: { one: string; } & U & U & U & U & U; deeper: (child: U) => { result: { one: string; } & U & U & U & U & U & U; deeper: (child: U) => { result: { one: string; } & U & U & U & U & U & U & U; deeper: (child: U) => { result: { one: string; } & U & U & U & U & U & U & U & U; deeper: (child: U) => { result: { one: string; } & U & U & U & U & U & U & U & U & U; deeper: (child: U) => { result: { one: string; } & U & U & U & U & U & U & U & U & U & U; deeper: (child: U) => { result: { one: string; } & U & U & U & U & U & U & U & U & U & U & U; deeper: any; }; }; }; }; }; }; }; }; }; }; } +>p1 : { result: { one: string; }; deeper: (child: U) => { result: { one: string; } & U; deeper: (child: U) => { result: { one: string; } & U & U; deeper: (child: U) => { result: { one: string; } & U & U & U; deeper: (child: U) => { result: { one: string; } & U & U & U & U; deeper: (child: U) => { result: { one: string; } & U & U & U & U & U; deeper: (child: U) => { result: { one: string; } & U & U & U & U & U & U; deeper: (child: U) => { result: { one: string; } & U & U & U & U & U & U & U; deeper: (child: U) => { result: { one: string; } & U & U & U & U & U & U & U & U; deeper: (child: U) => { result: { one: string; } & U & U & U & U & U & U & U & U & U; deeper: (child: U) => { result: { one: string; } & U & U & U & U & U & U & U & U & U & U; deeper: (child: U) => any; }; }; }; }; }; }; }; }; }; }; } +>deeper : (child: U) => { result: { one: string; } & U; deeper: (child: U) => { result: { one: string; } & U & U; deeper: (child: U) => { result: { one: string; } & U & U & U; deeper: (child: U) => { result: { one: string; } & U & U & U & U; deeper: (child: U) => { result: { one: string; } & U & U & U & U & U; deeper: (child: U) => { result: { one: string; } & U & U & U & U & U & U; deeper: (child: U) => { result: { one: string; } & U & U & U & U & U & U & U; deeper: (child: U) => { result: { one: string; } & U & U & U & U & U & U & U & U; deeper: (child: U) => { result: { one: string; } & U & U & U & U & U & U & U & U & U; deeper: (child: U) => { result: { one: string; } & U & U & U & U & U & U & U & U & U & U; deeper: (child: U) => { result: { one: string; } & U & U & U & U & U & U & U & U & U & U & U; deeper: any; }; }; }; }; }; }; }; }; }; }; } +>{ two: '2' } : { two: string; } +>two : string +>'2' : "2" + +void p2.result.one; +>void p2.result.one : undefined +>p2.result.one : string +>p2.result : { one: string; } & { two: string; } +>p2 : { result: { one: string; } & { two: string; }; deeper: (child: U) => { result: { one: string; } & { two: string; } & U; deeper: (child: U) => { result: { one: string; } & { two: string; } & U & U; deeper: (child: U) => { result: { one: string; } & { two: string; } & U & U & U; deeper: (child: U) => { result: { one: string; } & { two: string; } & U & U & U & U; deeper: (child: U) => { result: { one: string; } & { two: string; } & U & U & U & U & U; deeper: (child: U) => { result: { one: string; } & { two: string; } & U & U & U & U & U & U; deeper: (child: U) => { result: { one: string; } & { two: string; } & U & U & U & U & U & U & U; deeper: (child: U) => { result: { one: string; } & { two: string; } & U & U & U & U & U & U & U & U; deeper: (child: U) => { result: { one: string; } & { two: string; } & U & U & U & U & U & U & U & U & U; deeper: (child: U) => { result: { one: string; } & { two: string; } & U & U & U & U & U & U & U & U & U & U; deeper: (child: U) => any; }; }; }; }; }; }; }; }; }; }; } +>result : { one: string; } & { two: string; } +>one : string + +void p2.result.two; +>void p2.result.two : undefined +>p2.result.two : string +>p2.result : { one: string; } & { two: string; } +>p2 : { result: { one: string; } & { two: string; }; deeper: (child: U) => { result: { one: string; } & { two: string; } & U; deeper: (child: U) => { result: { one: string; } & { two: string; } & U & U; deeper: (child: U) => { result: { one: string; } & { two: string; } & U & U & U; deeper: (child: U) => { result: { one: string; } & { two: string; } & U & U & U & U; deeper: (child: U) => { result: { one: string; } & { two: string; } & U & U & U & U & U; deeper: (child: U) => { result: { one: string; } & { two: string; } & U & U & U & U & U & U; deeper: (child: U) => { result: { one: string; } & { two: string; } & U & U & U & U & U & U & U; deeper: (child: U) => { result: { one: string; } & { two: string; } & U & U & U & U & U & U & U & U; deeper: (child: U) => { result: { one: string; } & { two: string; } & U & U & U & U & U & U & U & U & U; deeper: (child: U) => { result: { one: string; } & { two: string; } & U & U & U & U & U & U & U & U & U & U; deeper: (child: U) => any; }; }; }; }; }; }; }; }; }; }; } +>result : { one: string; } & { two: string; } +>two : string + +let p3 = p2.deeper({ three: '3' }) +>p3 : { result: { one: string; } & { two: string; } & { three: string; }; deeper: (child: U) => { result: { one: string; } & { two: string; } & { three: string; } & U; deeper: (child: U) => { result: { one: string; } & { two: string; } & { three: string; } & U & U; deeper: (child: U) => { result: { one: string; } & { two: string; } & { three: string; } & U & U & U; deeper: (child: U) => { result: { one: string; } & { two: string; } & { three: string; } & U & U & U & U; deeper: (child: U) => { result: { one: string; } & { two: string; } & { three: string; } & U & U & U & U & U; deeper: (child: U) => { result: { one: string; } & { two: string; } & { three: string; } & U & U & U & U & U & U; deeper: (child: U) => { result: { one: string; } & { two: string; } & { three: string; } & U & U & U & U & U & U & U; deeper: (child: U) => { result: { one: string; } & { two: string; } & { three: string; } & U & U & U & U & U & U & U & U; deeper: (child: U) => { result: { one: string; } & { two: string; } & { three: string; } & U & U & U & U & U & U & U & U & U; deeper: (child: U) => { result: { one: string; } & { two: string; } & { three: string; } & U & U & U & U & U & U & U & U & U & U; deeper: (child: U) => any; }; }; }; }; }; }; }; }; }; }; } +>p2.deeper({ three: '3' }) : { result: { one: string; } & { two: string; } & { three: string; }; deeper: (child: U) => { result: { one: string; } & { two: string; } & { three: string; } & U; deeper: (child: U) => { result: { one: string; } & { two: string; } & { three: string; } & U & U; deeper: (child: U) => { result: { one: string; } & { two: string; } & { three: string; } & U & U & U; deeper: (child: U) => { result: { one: string; } & { two: string; } & { three: string; } & U & U & U & U; deeper: (child: U) => { result: { one: string; } & { two: string; } & { three: string; } & U & U & U & U & U; deeper: (child: U) => { result: { one: string; } & { two: string; } & { three: string; } & U & U & U & U & U & U; deeper: (child: U) => { result: { one: string; } & { two: string; } & { three: string; } & U & U & U & U & U & U & U; deeper: (child: U) => { result: { one: string; } & { two: string; } & { three: string; } & U & U & U & U & U & U & U & U; deeper: (child: U) => { result: { one: string; } & { two: string; } & { three: string; } & U & U & U & U & U & U & U & U & U; deeper: (child: U) => { result: { one: string; } & { two: string; } & { three: string; } & U & U & U & U & U & U & U & U & U & U; deeper: (child: U) => any; }; }; }; }; }; }; }; }; }; }; } +>p2.deeper : (child: U) => { result: { one: string; } & { two: string; } & U; deeper: (child: U) => { result: { one: string; } & { two: string; } & U & U; deeper: (child: U) => { result: { one: string; } & { two: string; } & U & U & U; deeper: (child: U) => { result: { one: string; } & { two: string; } & U & U & U & U; deeper: (child: U) => { result: { one: string; } & { two: string; } & U & U & U & U & U; deeper: (child: U) => { result: { one: string; } & { two: string; } & U & U & U & U & U & U; deeper: (child: U) => { result: { one: string; } & { two: string; } & U & U & U & U & U & U & U; deeper: (child: U) => { result: { one: string; } & { two: string; } & U & U & U & U & U & U & U & U; deeper: (child: U) => { result: { one: string; } & { two: string; } & U & U & U & U & U & U & U & U & U; deeper: (child: U) => { result: { one: string; } & { two: string; } & U & U & U & U & U & U & U & U & U & U; deeper: (child: U) => { result: { one: string; } & { two: string; } & U & U & U & U & U & U & U & U & U & U & U; deeper: any; }; }; }; }; }; }; }; }; }; }; } +>p2 : { result: { one: string; } & { two: string; }; deeper: (child: U) => { result: { one: string; } & { two: string; } & U; deeper: (child: U) => { result: { one: string; } & { two: string; } & U & U; deeper: (child: U) => { result: { one: string; } & { two: string; } & U & U & U; deeper: (child: U) => { result: { one: string; } & { two: string; } & U & U & U & U; deeper: (child: U) => { result: { one: string; } & { two: string; } & U & U & U & U & U; deeper: (child: U) => { result: { one: string; } & { two: string; } & U & U & U & U & U & U; deeper: (child: U) => { result: { one: string; } & { two: string; } & U & U & U & U & U & U & U; deeper: (child: U) => { result: { one: string; } & { two: string; } & U & U & U & U & U & U & U & U; deeper: (child: U) => { result: { one: string; } & { two: string; } & U & U & U & U & U & U & U & U & U; deeper: (child: U) => { result: { one: string; } & { two: string; } & U & U & U & U & U & U & U & U & U & U; deeper: (child: U) => any; }; }; }; }; }; }; }; }; }; }; } +>deeper : (child: U) => { result: { one: string; } & { two: string; } & U; deeper: (child: U) => { result: { one: string; } & { two: string; } & U & U; deeper: (child: U) => { result: { one: string; } & { two: string; } & U & U & U; deeper: (child: U) => { result: { one: string; } & { two: string; } & U & U & U & U; deeper: (child: U) => { result: { one: string; } & { two: string; } & U & U & U & U & U; deeper: (child: U) => { result: { one: string; } & { two: string; } & U & U & U & U & U & U; deeper: (child: U) => { result: { one: string; } & { two: string; } & U & U & U & U & U & U & U; deeper: (child: U) => { result: { one: string; } & { two: string; } & U & U & U & U & U & U & U & U; deeper: (child: U) => { result: { one: string; } & { two: string; } & U & U & U & U & U & U & U & U & U; deeper: (child: U) => { result: { one: string; } & { two: string; } & U & U & U & U & U & U & U & U & U & U; deeper: (child: U) => { result: { one: string; } & { two: string; } & U & U & U & U & U & U & U & U & U & U & U; deeper: any; }; }; }; }; }; }; }; }; }; }; } +>{ three: '3' } : { three: string; } +>three : string +>'3' : "3" + +void p3.result.one; +>void p3.result.one : undefined +>p3.result.one : string +>p3.result : { one: string; } & { two: string; } & { three: string; } +>p3 : { result: { one: string; } & { two: string; } & { three: string; }; deeper: (child: U) => { result: { one: string; } & { two: string; } & { three: string; } & U; deeper: (child: U) => { result: { one: string; } & { two: string; } & { three: string; } & U & U; deeper: (child: U) => { result: { one: string; } & { two: string; } & { three: string; } & U & U & U; deeper: (child: U) => { result: { one: string; } & { two: string; } & { three: string; } & U & U & U & U; deeper: (child: U) => { result: { one: string; } & { two: string; } & { three: string; } & U & U & U & U & U; deeper: (child: U) => { result: { one: string; } & { two: string; } & { three: string; } & U & U & U & U & U & U; deeper: (child: U) => { result: { one: string; } & { two: string; } & { three: string; } & U & U & U & U & U & U & U; deeper: (child: U) => { result: { one: string; } & { two: string; } & { three: string; } & U & U & U & U & U & U & U & U; deeper: (child: U) => { result: { one: string; } & { two: string; } & { three: string; } & U & U & U & U & U & U & U & U & U; deeper: (child: U) => { result: { one: string; } & { two: string; } & { three: string; } & U & U & U & U & U & U & U & U & U & U; deeper: (child: U) => any; }; }; }; }; }; }; }; }; }; }; } +>result : { one: string; } & { two: string; } & { three: string; } +>one : string + +void p3.result.two; +>void p3.result.two : undefined +>p3.result.two : string +>p3.result : { one: string; } & { two: string; } & { three: string; } +>p3 : { result: { one: string; } & { two: string; } & { three: string; }; deeper: (child: U) => { result: { one: string; } & { two: string; } & { three: string; } & U; deeper: (child: U) => { result: { one: string; } & { two: string; } & { three: string; } & U & U; deeper: (child: U) => { result: { one: string; } & { two: string; } & { three: string; } & U & U & U; deeper: (child: U) => { result: { one: string; } & { two: string; } & { three: string; } & U & U & U & U; deeper: (child: U) => { result: { one: string; } & { two: string; } & { three: string; } & U & U & U & U & U; deeper: (child: U) => { result: { one: string; } & { two: string; } & { three: string; } & U & U & U & U & U & U; deeper: (child: U) => { result: { one: string; } & { two: string; } & { three: string; } & U & U & U & U & U & U & U; deeper: (child: U) => { result: { one: string; } & { two: string; } & { three: string; } & U & U & U & U & U & U & U & U; deeper: (child: U) => { result: { one: string; } & { two: string; } & { three: string; } & U & U & U & U & U & U & U & U & U; deeper: (child: U) => { result: { one: string; } & { two: string; } & { three: string; } & U & U & U & U & U & U & U & U & U & U; deeper: (child: U) => any; }; }; }; }; }; }; }; }; }; }; } +>result : { one: string; } & { two: string; } & { three: string; } +>two : string + +void p3.result.three; +>void p3.result.three : undefined +>p3.result.three : string +>p3.result : { one: string; } & { two: string; } & { three: string; } +>p3 : { result: { one: string; } & { two: string; } & { three: string; }; deeper: (child: U) => { result: { one: string; } & { two: string; } & { three: string; } & U; deeper: (child: U) => { result: { one: string; } & { two: string; } & { three: string; } & U & U; deeper: (child: U) => { result: { one: string; } & { two: string; } & { three: string; } & U & U & U; deeper: (child: U) => { result: { one: string; } & { two: string; } & { three: string; } & U & U & U & U; deeper: (child: U) => { result: { one: string; } & { two: string; } & { three: string; } & U & U & U & U & U; deeper: (child: U) => { result: { one: string; } & { two: string; } & { three: string; } & U & U & U & U & U & U; deeper: (child: U) => { result: { one: string; } & { two: string; } & { three: string; } & U & U & U & U & U & U & U; deeper: (child: U) => { result: { one: string; } & { two: string; } & { three: string; } & U & U & U & U & U & U & U & U; deeper: (child: U) => { result: { one: string; } & { two: string; } & { three: string; } & U & U & U & U & U & U & U & U & U; deeper: (child: U) => { result: { one: string; } & { two: string; } & { three: string; } & U & U & U & U & U & U & U & U & U & U; deeper: (child: U) => any; }; }; }; }; }; }; }; }; }; }; } +>result : { one: string; } & { two: string; } & { three: string; } +>three : string + diff --git a/tests/cases/compiler/declarationsWithRecursiveInternalTypesProduceUniqueTypeParams.ts b/tests/cases/compiler/declarationsWithRecursiveInternalTypesProduceUniqueTypeParams.ts new file mode 100644 index 00000000000..777b3c3ccb2 --- /dev/null +++ b/tests/cases/compiler/declarationsWithRecursiveInternalTypesProduceUniqueTypeParams.ts @@ -0,0 +1,42 @@ +// @declaration: true +// @lib: es6 + +// Note that both of the following have an `any` in their return type from where we bottom out the type printout +// for having too many instances of the same symbol nesting. + +// Slightly simplified repro from https://github.com/microsoft/TypeScript/issues/30732 so it's easier to read and debug +export type Key = keyof U; +export type Value, U> = U[K]; +export const updateIfChanged = (t: T) => { + const reduce = (u: U, update: (u: U) => T) => { + const set = (newU: U) => Object.is(u, newU) ? t : update(newU); + return Object.assign( + >(key: K) => + reduce>(u[key as keyof U] as Value, (v: Value) => { + return update(Object.assign(Array.isArray(u) ? [] : {}, u, { [key]: v })); + }), + { map: (updater: (u: U) => U) => set(updater(u)), set }); + }; + return reduce(t, (t: T) => t); +}; + +// example from https://github.com/microsoft/TypeScript/issues/31605 + +export const testRecFun = (parent: T) => { + return { + result: parent, + deeper: (child: U) => + testRecFun({ ...parent, ...child }) + }; +} + + +let p1 = testRecFun({ one: '1' }) +void p1.result.one; +let p2 = p1.deeper({ two: '2' }) +void p2.result.one; +void p2.result.two; +let p3 = p2.deeper({ three: '3' }) +void p3.result.one; +void p3.result.two; +void p3.result.three;