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
This commit is contained in:
Wesley Wigham 2019-07-10 17:12:20 -07:00 committed by GitHub
parent daf0a73346
commit 6839973bf7
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 658 additions and 18 deletions

View File

@ -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<true>;
typeParameterNames?: Map<Identifier>;
typeParameterNamesByText?: Map<true>;
}
function isDefaultBindingContext(location: Node) {

View File

@ -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<U> = keyof U;
export type Value<K extends Key<U>, U> = U[K];
export const updateIfChanged = <T>(t: T) => {
const reduce = <U>(u: U, update: (u: U) => T) => {
const set = (newU: U) => Object.is(u, newU) ? t : update(newU);
return Object.assign(
<K extends Key<U>>(key: K) =>
reduce<Value<K, U>>(u[key as keyof U] as Value<K, U>, (v: Value<K, U>) => {
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);
};
// example from https://github.com/microsoft/TypeScript/issues/31605
export const testRecFun = <T extends Object>(parent: T) => {
return {
result: parent,
deeper: <U extends Object>(child: U) =>
testRecFun<T & U>({ ...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<U> = keyof U;
export declare type Value<K extends Key<U>, U> = U[K];
export declare const updateIfChanged: <T>(t: T) => (<K extends keyof T>(key: K) => (<K_1 extends keyof T[K]>(key: K_1) => (<K_2 extends keyof T[K][K_1]>(key: K_2) => (<K_3 extends keyof T[K][K_1][K_2]>(key: K_3) => (<K_4 extends keyof T[K][K_1][K_2][K_3]>(key: K_4) => (<K_5 extends keyof T[K][K_1][K_2][K_3][K_4]>(key: K_5) => (<K_6 extends keyof T[K][K_1][K_2][K_3][K_4][K_5]>(key: K_6) => (<K_7 extends keyof T[K][K_1][K_2][K_3][K_4][K_5][K_6]>(key: K_7) => (<K_8 extends keyof T[K][K_1][K_2][K_3][K_4][K_5][K_6][K_7]>(key: K_8) => (<K_9 extends keyof T[K][K_1][K_2][K_3][K_4][K_5][K_6][K_7][K_8]>(key: K_9) => (<K_10 extends keyof T[K][K_1][K_2][K_3][K_4][K_5][K_6][K_7][K_8][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: <T extends Object>(parent: T) => {
result: T;
deeper: <U extends Object>(child: U) => {
result: T & U;
deeper: <U_1 extends Object>(child: U_1) => {
result: T & U & U_1;
deeper: <U_2 extends Object>(child: U_2) => {
result: T & U & U_1 & U_2;
deeper: <U_3 extends Object>(child: U_3) => {
result: T & U & U_1 & U_2 & U_3;
deeper: <U_4 extends Object>(child: U_4) => {
result: T & U & U_1 & U_2 & U_3 & U_4;
deeper: <U_5 extends Object>(child: U_5) => {
result: T & U & U_1 & U_2 & U_3 & U_4 & U_5;
deeper: <U_6 extends Object>(child: U_6) => {
result: T & U & U_1 & U_2 & U_3 & U_4 & U_5 & U_6;
deeper: <U_7 extends Object>(child: U_7) => {
result: T & U & U_1 & U_2 & U_3 & U_4 & U_5 & U_6 & U_7;
deeper: <U_8 extends Object>(child: U_8) => {
result: T & U & U_1 & U_2 & U_3 & U_4 & U_5 & U_6 & U_7 & U_8;
deeper: <U_9 extends Object>(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: <U_10 extends Object>(child: U_10) => any;
};
};
};
};
};
};
};
};
};
};
};

View File

@ -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<U> = 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<K extends Key<U>, 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: 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: 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, --, --))
<K extends Key<U>>(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<Value<K, U>>(u[key as keyof U] as Value<K, U>, (v: Value<K, U>) => {
>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) => 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 = <T extends Object>(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: <U extends Object>(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<T & U>({ ...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))

View File

@ -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<U> = keyof U;
>Key : keyof U
export type Value<K extends Key<U>, U> = U[K];
>Value : U[K]
export const updateIfChanged = <T>(t: T) => {
>updateIfChanged : <T>(t: T) => (<K extends keyof T>(key: K) => (<K extends keyof T[K]>(key: K) => (<K extends keyof T[K][K]>(key: K) => (<K extends keyof T[K][K][K]>(key: K) => (<K extends keyof T[K][K][K][K]>(key: K) => (<K extends keyof T[K][K][K][K][K]>(key: K) => (<K extends keyof T[K][K][K][K][K][K]>(key: K) => (<K extends keyof T[K][K][K][K][K][K][K]>(key: K) => (<K extends keyof T[K][K][K][K][K][K][K][K]>(key: K) => (<K extends keyof T[K][K][K][K][K][K][K][K][K]>(key: K) => (<K extends keyof T[K][K][K][K][K][K][K][K][K][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: T) => { const reduce = <U>(u: U, update: (u: U) => T) => { const set = (newU: U) => Object.is(u, newU) ? t : update(newU); return Object.assign( <K extends Key<U>>(key: K) => reduce<Value<K, U>>(u[key as keyof U] as Value<K, U>, (v: Value<K, U>) => { 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>(t: T) => (<K extends keyof T>(key: K) => (<K extends keyof T[K]>(key: K) => (<K extends keyof T[K][K]>(key: K) => (<K extends keyof T[K][K][K]>(key: K) => (<K extends keyof T[K][K][K][K]>(key: K) => (<K extends keyof T[K][K][K][K][K]>(key: K) => (<K extends keyof T[K][K][K][K][K][K]>(key: K) => (<K extends keyof T[K][K][K][K][K][K][K]>(key: K) => (<K extends keyof T[K][K][K][K][K][K][K][K]>(key: K) => (<K extends keyof T[K][K][K][K][K][K][K][K][K]>(key: K) => (<K extends keyof T[K][K][K][K][K][K][K][K][K][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: U, update: (u: U) => T) => {
>reduce : <U>(u: U, update: (u: U) => T) => (<K extends keyof U>(key: K) => (<K extends keyof U[K]>(key: K) => (<K extends keyof U[K][K]>(key: K) => (<K extends keyof U[K][K][K]>(key: K) => (<K extends keyof U[K][K][K][K]>(key: K) => (<K extends keyof U[K][K][K][K][K]>(key: K) => (<K extends keyof U[K][K][K][K][K][K]>(key: K) => (<K extends keyof U[K][K][K][K][K][K][K]>(key: K) => (<K extends keyof U[K][K][K][K][K][K][K][K]>(key: K) => (<K extends keyof U[K][K][K][K][K][K][K][K][K]>(key: K) => (<K extends keyof U[K][K][K][K][K][K][K][K][K][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: U, update: (u: U) => T) => { const set = (newU: U) => Object.is(u, newU) ? t : update(newU); return Object.assign( <K extends Key<U>>(key: K) => reduce<Value<K, U>>(u[key as keyof U] as Value<K, U>, (v: Value<K, U>) => { return update(Object.assign(Array.isArray(u) ? [] : {}, u, { [key]: v })); }), { map: (updater: (u: U) => U) => set(updater(u)), set }); } : <U>(u: U, update: (u: U) => T) => (<K extends keyof U>(key: K) => (<K extends keyof U[K]>(key: K) => (<K extends keyof U[K][K]>(key: K) => (<K extends keyof U[K][K][K]>(key: K) => (<K extends keyof U[K][K][K][K]>(key: K) => (<K extends keyof U[K][K][K][K][K]>(key: K) => (<K extends keyof U[K][K][K][K][K][K]>(key: K) => (<K extends keyof U[K][K][K][K][K][K][K]>(key: K) => (<K extends keyof U[K][K][K][K][K][K][K][K]>(key: K) => (<K extends keyof U[K][K][K][K][K][K][K][K][K]>(key: K) => (<K extends keyof U[K][K][K][K][K][K][K][K][K][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( <K extends Key<U>>(key: K) => reduce<Value<K, U>>(u[key as keyof U] as Value<K, U>, (v: Value<K, U>) => { return update(Object.assign(Array.isArray(u) ? [] : {}, u, { [key]: v })); }), { map: (updater: (u: U) => U) => set(updater(u)), set }) : (<K extends keyof U>(key: K) => (<K extends keyof U[K]>(key: K) => (<K extends keyof U[K][K]>(key: K) => (<K extends keyof U[K][K][K]>(key: K) => (<K extends keyof U[K][K][K][K]>(key: K) => (<K extends keyof U[K][K][K][K][K]>(key: K) => (<K extends keyof U[K][K][K][K][K][K]>(key: K) => (<K extends keyof U[K][K][K][K][K][K][K]>(key: K) => (<K extends keyof U[K][K][K][K][K][K][K][K]>(key: K) => (<K extends keyof U[K][K][K][K][K][K][K][K][K]>(key: K) => (<K extends keyof U[K][K][K][K][K][K][K][K][K][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 : { <T, U>(target: T, source: U): T & U; <T, U, V>(target: T, source1: U, source2: V): T & U & V; <T, U, V, W>(target: T, source1: U, source2: V, source3: W): T & U & V & W; (target: object, ...sources: any[]): any; }
>Object : ObjectConstructor
>assign : { <T, U>(target: T, source: U): T & U; <T, U, V>(target: T, source1: U, source2: V): T & U & V; <T, U, V, W>(target: T, source1: U, source2: V, source3: W): T & U & V & W; (target: object, ...sources: any[]): any; }
<K extends Key<U>>(key: K) =>
><K extends Key<U>>(key: K) => reduce<Value<K, U>>(u[key as keyof U] as Value<K, U>, (v: Value<K, U>) => { return update(Object.assign(Array.isArray(u) ? [] : {}, u, { [key]: v })); }) : <K extends keyof U>(key: K) => (<K extends keyof U[K]>(key: K) => (<K extends keyof U[K][K]>(key: K) => (<K extends keyof U[K][K][K]>(key: K) => (<K extends keyof U[K][K][K][K]>(key: K) => (<K extends keyof U[K][K][K][K][K]>(key: K) => (<K extends keyof U[K][K][K][K][K][K]>(key: K) => (<K extends keyof U[K][K][K][K][K][K][K]>(key: K) => (<K extends keyof U[K][K][K][K][K][K][K][K]>(key: K) => (<K extends keyof U[K][K][K][K][K][K][K][K][K]>(key: K) => (<K extends keyof U[K][K][K][K][K][K][K][K][K][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<Value<K, U>>(u[key as keyof U] as Value<K, U>, (v: Value<K, U>) => {
>reduce<Value<K, U>>(u[key as keyof U] as Value<K, U>, (v: Value<K, U>) => { return update(Object.assign(Array.isArray(u) ? [] : {}, u, { [key]: v })); }) : (<K extends keyof U[K]>(key: K) => (<K extends keyof U[K][K]>(key: K) => (<K extends keyof U[K][K][K]>(key: K) => (<K extends keyof U[K][K][K][K]>(key: K) => (<K extends keyof U[K][K][K][K][K]>(key: K) => (<K extends keyof U[K][K][K][K][K][K]>(key: K) => (<K extends keyof U[K][K][K][K][K][K][K]>(key: K) => (<K extends keyof U[K][K][K][K][K][K][K][K]>(key: K) => (<K extends keyof U[K][K][K][K][K][K][K][K][K]>(key: K) => (<K extends keyof U[K][K][K][K][K][K][K][K][K][K]>(key: K) => (<K extends keyof U[K][K][K][K][K][K][K][K][K][K][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: U, update: (u: U) => T) => (<K extends keyof U>(key: K) => (<K extends keyof U[K]>(key: K) => (<K extends keyof U[K][K]>(key: K) => (<K extends keyof U[K][K][K]>(key: K) => (<K extends keyof U[K][K][K][K]>(key: K) => (<K extends keyof U[K][K][K][K][K]>(key: K) => (<K extends keyof U[K][K][K][K][K][K]>(key: K) => (<K extends keyof U[K][K][K][K][K][K][K]>(key: K) => (<K extends keyof U[K][K][K][K][K][K][K][K]>(key: K) => (<K extends keyof U[K][K][K][K][K][K][K][K][K]>(key: K) => (<K extends keyof U[K][K][K][K][K][K][K][K][K][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<K, U> : U[K]
>u[key as keyof U] : U[keyof U]
>u : U
>key as keyof U : keyof U
>key : K
>(v: Value<K, U>) => { 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 : { <T, U>(target: T, source: U): T & U; <T, U, V>(target: T, source1: U, source2: V): T & U & V; <T, U, V, W>(target: T, source1: U, source2: V, source3: W): T & U & V & W; (target: object, ...sources: any[]): any; }
>Object : ObjectConstructor
>assign : { <T, U>(target: T, source: U): T & U; <T, U, V>(target: T, source1: U, source2: V): T & U & V; <T, U, V, W>(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) => t);
>reduce<T>(t, (t: T) => t) : (<K extends keyof T>(key: K) => (<K extends keyof T[K]>(key: K) => (<K extends keyof T[K][K]>(key: K) => (<K extends keyof T[K][K][K]>(key: K) => (<K extends keyof T[K][K][K][K]>(key: K) => (<K extends keyof T[K][K][K][K][K]>(key: K) => (<K extends keyof T[K][K][K][K][K][K]>(key: K) => (<K extends keyof T[K][K][K][K][K][K][K]>(key: K) => (<K extends keyof T[K][K][K][K][K][K][K][K]>(key: K) => (<K extends keyof T[K][K][K][K][K][K][K][K][K]>(key: K) => (<K extends keyof T[K][K][K][K][K][K][K][K][K][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: U, update: (u: U) => T) => (<K extends keyof U>(key: K) => (<K extends keyof U[K]>(key: K) => (<K extends keyof U[K][K]>(key: K) => (<K extends keyof U[K][K][K]>(key: K) => (<K extends keyof U[K][K][K][K]>(key: K) => (<K extends keyof U[K][K][K][K][K]>(key: K) => (<K extends keyof U[K][K][K][K][K][K]>(key: K) => (<K extends keyof U[K][K][K][K][K][K][K]>(key: K) => (<K extends keyof U[K][K][K][K][K][K][K][K]>(key: K) => (<K extends keyof U[K][K][K][K][K][K][K][K][K]>(key: K) => (<K extends keyof U[K][K][K][K][K][K][K][K][K][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 = <T extends Object>(parent: T) => {
>testRecFun : <T extends Object>(parent: T) => { result: T; deeper: <U extends Object>(child: U) => { result: T & U; deeper: <U extends Object>(child: U) => { result: T & U & U; deeper: <U extends Object>(child: U) => { result: T & U & U & U; deeper: <U extends Object>(child: U) => { result: T & U & U & U & U; deeper: <U extends Object>(child: U) => { result: T & U & U & U & U & U; deeper: <U extends Object>(child: U) => { result: T & U & U & U & U & U & U; deeper: <U extends Object>(child: U) => { result: T & U & U & U & U & U & U & U; deeper: <U extends Object>(child: U) => { result: T & U & U & U & U & U & U & U & U; deeper: <U extends Object>(child: U) => { result: T & U & U & U & U & U & U & U & U & U; deeper: <U extends Object>(child: U) => { result: T & U & U & U & U & U & U & U & U & U & U; deeper: <U extends Object>(child: U) => any; }; }; }; }; }; }; }; }; }; }; }
><T extends Object>(parent: T) => { return { result: parent, deeper: <U extends Object>(child: U) => testRecFun<T & U>({ ...parent, ...child }) };} : <T extends Object>(parent: T) => { result: T; deeper: <U extends Object>(child: U) => { result: T & U; deeper: <U extends Object>(child: U) => { result: T & U & U; deeper: <U extends Object>(child: U) => { result: T & U & U & U; deeper: <U extends Object>(child: U) => { result: T & U & U & U & U; deeper: <U extends Object>(child: U) => { result: T & U & U & U & U & U; deeper: <U extends Object>(child: U) => { result: T & U & U & U & U & U & U; deeper: <U extends Object>(child: U) => { result: T & U & U & U & U & U & U & U; deeper: <U extends Object>(child: U) => { result: T & U & U & U & U & U & U & U & U; deeper: <U extends Object>(child: U) => { result: T & U & U & U & U & U & U & U & U & U; deeper: <U extends Object>(child: U) => { result: T & U & U & U & U & U & U & U & U & U & U; deeper: <U extends Object>(child: U) => any; }; }; }; }; }; }; }; }; }; }; }
>parent : T
return {
>{ result: parent, deeper: <U extends Object>(child: U) => testRecFun<T & U>({ ...parent, ...child }) } : { result: T; deeper: <U extends Object>(child: U) => { result: T & U; deeper: <U extends Object>(child: U) => { result: T & U & U; deeper: <U extends Object>(child: U) => { result: T & U & U & U; deeper: <U extends Object>(child: U) => { result: T & U & U & U & U; deeper: <U extends Object>(child: U) => { result: T & U & U & U & U & U; deeper: <U extends Object>(child: U) => { result: T & U & U & U & U & U & U; deeper: <U extends Object>(child: U) => { result: T & U & U & U & U & U & U & U; deeper: <U extends Object>(child: U) => { result: T & U & U & U & U & U & U & U & U; deeper: <U extends Object>(child: U) => { result: T & U & U & U & U & U & U & U & U & U; deeper: <U extends Object>(child: U) => { result: T & U & U & U & U & U & U & U & U & U & U; deeper: <U extends Object>(child: U) => any; }; }; }; }; }; }; }; }; }; }; }
result: parent,
>result : T
>parent : T
deeper: <U extends Object>(child: U) =>
>deeper : <U extends Object>(child: U) => { result: T & U; deeper: <U extends Object>(child: U) => { result: T & U & U; deeper: <U extends Object>(child: U) => { result: T & U & U & U; deeper: <U extends Object>(child: U) => { result: T & U & U & U & U; deeper: <U extends Object>(child: U) => { result: T & U & U & U & U & U; deeper: <U extends Object>(child: U) => { result: T & U & U & U & U & U & U; deeper: <U extends Object>(child: U) => { result: T & U & U & U & U & U & U & U; deeper: <U extends Object>(child: U) => { result: T & U & U & U & U & U & U & U & U; deeper: <U extends Object>(child: U) => { result: T & U & U & U & U & U & U & U & U & U; deeper: <U extends Object>(child: U) => { result: T & U & U & U & U & U & U & U & U & U & U; deeper: <U extends Object>(child: U) => { result: T & U & U & U & U & U & U & U & U & U & U & U; deeper: any; }; }; }; }; }; }; }; }; }; }; }
><U extends Object>(child: U) => testRecFun<T & U>({ ...parent, ...child }) : <U extends Object>(child: U) => { result: T & U; deeper: <U extends Object>(child: U) => { result: T & U & U; deeper: <U extends Object>(child: U) => { result: T & U & U & U; deeper: <U extends Object>(child: U) => { result: T & U & U & U & U; deeper: <U extends Object>(child: U) => { result: T & U & U & U & U & U; deeper: <U extends Object>(child: U) => { result: T & U & U & U & U & U & U; deeper: <U extends Object>(child: U) => { result: T & U & U & U & U & U & U & U; deeper: <U extends Object>(child: U) => { result: T & U & U & U & U & U & U & U & U; deeper: <U extends Object>(child: U) => { result: T & U & U & U & U & U & U & U & U & U; deeper: <U extends Object>(child: U) => { result: T & U & U & U & U & U & U & U & U & U & U; deeper: <U extends Object>(child: U) => { result: T & U & U & U & U & U & U & U & U & U & U & U; deeper: any; }; }; }; }; }; }; }; }; }; }; }
>child : U
testRecFun<T & U>({ ...parent, ...child })
>testRecFun<T & U>({ ...parent, ...child }) : { result: T & U; deeper: <U extends Object>(child: U) => { result: T & U & U; deeper: <U extends Object>(child: U) => { result: T & U & U & U; deeper: <U extends Object>(child: U) => { result: T & U & U & U & U; deeper: <U extends Object>(child: U) => { result: T & U & U & U & U & U; deeper: <U extends Object>(child: U) => { result: T & U & U & U & U & U & U; deeper: <U extends Object>(child: U) => { result: T & U & U & U & U & U & U & U; deeper: <U extends Object>(child: U) => { result: T & U & U & U & U & U & U & U & U; deeper: <U extends Object>(child: U) => { result: T & U & U & U & U & U & U & U & U & U; deeper: <U extends Object>(child: U) => { result: T & U & U & U & U & U & U & U & U & U & U; deeper: <U extends Object>(child: U) => { result: T & U & U & U & U & U & U & U & U & U & U & U; deeper: <U extends Object>(child: U) => any; }; }; }; }; }; }; }; }; }; }; }
>testRecFun : <T extends Object>(parent: T) => { result: T; deeper: <U extends Object>(child: U) => { result: T & U; deeper: <U extends Object>(child: U) => { result: T & U & U; deeper: <U extends Object>(child: U) => { result: T & U & U & U; deeper: <U extends Object>(child: U) => { result: T & U & U & U & U; deeper: <U extends Object>(child: U) => { result: T & U & U & U & U & U; deeper: <U extends Object>(child: U) => { result: T & U & U & U & U & U & U; deeper: <U extends Object>(child: U) => { result: T & U & U & U & U & U & U & U; deeper: <U extends Object>(child: U) => { result: T & U & U & U & U & U & U & U & U; deeper: <U extends Object>(child: U) => { result: T & U & U & U & U & U & U & U & U & U; deeper: <U extends Object>(child: U) => { result: T & U & U & U & U & U & U & U & U & U & U; deeper: <U extends Object>(child: U) => any; }; }; }; }; }; }; }; }; }; }; }
>{ ...parent, ...child } : T & U
>parent : T
>child : U
};
}
let p1 = testRecFun({ one: '1' })
>p1 : { result: { one: string; }; deeper: <U extends Object>(child: U) => { result: { one: string; } & U; deeper: <U extends Object>(child: U) => { result: { one: string; } & U & U; deeper: <U extends Object>(child: U) => { result: { one: string; } & U & U & U; deeper: <U extends Object>(child: U) => { result: { one: string; } & U & U & U & U; deeper: <U extends Object>(child: U) => { result: { one: string; } & U & U & U & U & U; deeper: <U extends Object>(child: U) => { result: { one: string; } & U & U & U & U & U & U; deeper: <U extends Object>(child: U) => { result: { one: string; } & U & U & U & U & U & U & U; deeper: <U extends Object>(child: U) => { result: { one: string; } & U & U & U & U & U & U & U & U; deeper: <U extends Object>(child: U) => { result: { one: string; } & U & U & U & U & U & U & U & U & U; deeper: <U extends Object>(child: U) => { result: { one: string; } & U & U & U & U & U & U & U & U & U & U; deeper: <U extends Object>(child: U) => any; }; }; }; }; }; }; }; }; }; }; }
>testRecFun({ one: '1' }) : { result: { one: string; }; deeper: <U extends Object>(child: U) => { result: { one: string; } & U; deeper: <U extends Object>(child: U) => { result: { one: string; } & U & U; deeper: <U extends Object>(child: U) => { result: { one: string; } & U & U & U; deeper: <U extends Object>(child: U) => { result: { one: string; } & U & U & U & U; deeper: <U extends Object>(child: U) => { result: { one: string; } & U & U & U & U & U; deeper: <U extends Object>(child: U) => { result: { one: string; } & U & U & U & U & U & U; deeper: <U extends Object>(child: U) => { result: { one: string; } & U & U & U & U & U & U & U; deeper: <U extends Object>(child: U) => { result: { one: string; } & U & U & U & U & U & U & U & U; deeper: <U extends Object>(child: U) => { result: { one: string; } & U & U & U & U & U & U & U & U & U; deeper: <U extends Object>(child: U) => { result: { one: string; } & U & U & U & U & U & U & U & U & U & U; deeper: <U extends Object>(child: U) => any; }; }; }; }; }; }; }; }; }; }; }
>testRecFun : <T extends Object>(parent: T) => { result: T; deeper: <U extends Object>(child: U) => { result: T & U; deeper: <U extends Object>(child: U) => { result: T & U & U; deeper: <U extends Object>(child: U) => { result: T & U & U & U; deeper: <U extends Object>(child: U) => { result: T & U & U & U & U; deeper: <U extends Object>(child: U) => { result: T & U & U & U & U & U; deeper: <U extends Object>(child: U) => { result: T & U & U & U & U & U & U; deeper: <U extends Object>(child: U) => { result: T & U & U & U & U & U & U & U; deeper: <U extends Object>(child: U) => { result: T & U & U & U & U & U & U & U & U; deeper: <U extends Object>(child: U) => { result: T & U & U & U & U & U & U & U & U & U; deeper: <U extends Object>(child: U) => { result: T & U & U & U & U & U & U & U & U & U & U; deeper: <U extends Object>(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: <U extends Object>(child: U) => { result: { one: string; } & U; deeper: <U extends Object>(child: U) => { result: { one: string; } & U & U; deeper: <U extends Object>(child: U) => { result: { one: string; } & U & U & U; deeper: <U extends Object>(child: U) => { result: { one: string; } & U & U & U & U; deeper: <U extends Object>(child: U) => { result: { one: string; } & U & U & U & U & U; deeper: <U extends Object>(child: U) => { result: { one: string; } & U & U & U & U & U & U; deeper: <U extends Object>(child: U) => { result: { one: string; } & U & U & U & U & U & U & U; deeper: <U extends Object>(child: U) => { result: { one: string; } & U & U & U & U & U & U & U & U; deeper: <U extends Object>(child: U) => { result: { one: string; } & U & U & U & U & U & U & U & U & U; deeper: <U extends Object>(child: U) => { result: { one: string; } & U & U & U & U & U & U & U & U & U & U; deeper: <U extends Object>(child: U) => any; }; }; }; }; }; }; }; }; }; }; }
>result : { one: string; }
>one : string
let p2 = p1.deeper({ two: '2' })
>p2 : { result: { one: string; } & { two: string; }; deeper: <U extends Object>(child: U) => { result: { one: string; } & { two: string; } & U; deeper: <U extends Object>(child: U) => { result: { one: string; } & { two: string; } & U & U; deeper: <U extends Object>(child: U) => { result: { one: string; } & { two: string; } & U & U & U; deeper: <U extends Object>(child: U) => { result: { one: string; } & { two: string; } & U & U & U & U; deeper: <U extends Object>(child: U) => { result: { one: string; } & { two: string; } & U & U & U & U & U; deeper: <U extends Object>(child: U) => { result: { one: string; } & { two: string; } & U & U & U & U & U & U; deeper: <U extends Object>(child: U) => { result: { one: string; } & { two: string; } & U & U & U & U & U & U & U; deeper: <U extends Object>(child: U) => { result: { one: string; } & { two: string; } & U & U & U & U & U & U & U & U; deeper: <U extends Object>(child: U) => { result: { one: string; } & { two: string; } & U & U & U & U & U & U & U & U & U; deeper: <U extends Object>(child: U) => { result: { one: string; } & { two: string; } & U & U & U & U & U & U & U & U & U & U; deeper: <U extends Object>(child: U) => any; }; }; }; }; }; }; }; }; }; }; }
>p1.deeper({ two: '2' }) : { result: { one: string; } & { two: string; }; deeper: <U extends Object>(child: U) => { result: { one: string; } & { two: string; } & U; deeper: <U extends Object>(child: U) => { result: { one: string; } & { two: string; } & U & U; deeper: <U extends Object>(child: U) => { result: { one: string; } & { two: string; } & U & U & U; deeper: <U extends Object>(child: U) => { result: { one: string; } & { two: string; } & U & U & U & U; deeper: <U extends Object>(child: U) => { result: { one: string; } & { two: string; } & U & U & U & U & U; deeper: <U extends Object>(child: U) => { result: { one: string; } & { two: string; } & U & U & U & U & U & U; deeper: <U extends Object>(child: U) => { result: { one: string; } & { two: string; } & U & U & U & U & U & U & U; deeper: <U extends Object>(child: U) => { result: { one: string; } & { two: string; } & U & U & U & U & U & U & U & U; deeper: <U extends Object>(child: U) => { result: { one: string; } & { two: string; } & U & U & U & U & U & U & U & U & U; deeper: <U extends Object>(child: U) => { result: { one: string; } & { two: string; } & U & U & U & U & U & U & U & U & U & U; deeper: <U extends Object>(child: U) => any; }; }; }; }; }; }; }; }; }; }; }
>p1.deeper : <U extends Object>(child: U) => { result: { one: string; } & U; deeper: <U extends Object>(child: U) => { result: { one: string; } & U & U; deeper: <U extends Object>(child: U) => { result: { one: string; } & U & U & U; deeper: <U extends Object>(child: U) => { result: { one: string; } & U & U & U & U; deeper: <U extends Object>(child: U) => { result: { one: string; } & U & U & U & U & U; deeper: <U extends Object>(child: U) => { result: { one: string; } & U & U & U & U & U & U; deeper: <U extends Object>(child: U) => { result: { one: string; } & U & U & U & U & U & U & U; deeper: <U extends Object>(child: U) => { result: { one: string; } & U & U & U & U & U & U & U & U; deeper: <U extends Object>(child: U) => { result: { one: string; } & U & U & U & U & U & U & U & U & U; deeper: <U extends Object>(child: U) => { result: { one: string; } & U & U & U & U & U & U & U & U & U & U; deeper: <U extends Object>(child: U) => { result: { one: string; } & U & U & U & U & U & U & U & U & U & U & U; deeper: any; }; }; }; }; }; }; }; }; }; }; }
>p1 : { result: { one: string; }; deeper: <U extends Object>(child: U) => { result: { one: string; } & U; deeper: <U extends Object>(child: U) => { result: { one: string; } & U & U; deeper: <U extends Object>(child: U) => { result: { one: string; } & U & U & U; deeper: <U extends Object>(child: U) => { result: { one: string; } & U & U & U & U; deeper: <U extends Object>(child: U) => { result: { one: string; } & U & U & U & U & U; deeper: <U extends Object>(child: U) => { result: { one: string; } & U & U & U & U & U & U; deeper: <U extends Object>(child: U) => { result: { one: string; } & U & U & U & U & U & U & U; deeper: <U extends Object>(child: U) => { result: { one: string; } & U & U & U & U & U & U & U & U; deeper: <U extends Object>(child: U) => { result: { one: string; } & U & U & U & U & U & U & U & U & U; deeper: <U extends Object>(child: U) => { result: { one: string; } & U & U & U & U & U & U & U & U & U & U; deeper: <U extends Object>(child: U) => any; }; }; }; }; }; }; }; }; }; }; }
>deeper : <U extends Object>(child: U) => { result: { one: string; } & U; deeper: <U extends Object>(child: U) => { result: { one: string; } & U & U; deeper: <U extends Object>(child: U) => { result: { one: string; } & U & U & U; deeper: <U extends Object>(child: U) => { result: { one: string; } & U & U & U & U; deeper: <U extends Object>(child: U) => { result: { one: string; } & U & U & U & U & U; deeper: <U extends Object>(child: U) => { result: { one: string; } & U & U & U & U & U & U; deeper: <U extends Object>(child: U) => { result: { one: string; } & U & U & U & U & U & U & U; deeper: <U extends Object>(child: U) => { result: { one: string; } & U & U & U & U & U & U & U & U; deeper: <U extends Object>(child: U) => { result: { one: string; } & U & U & U & U & U & U & U & U & U; deeper: <U extends Object>(child: U) => { result: { one: string; } & U & U & U & U & U & U & U & U & U & U; deeper: <U extends Object>(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: <U extends Object>(child: U) => { result: { one: string; } & { two: string; } & U; deeper: <U extends Object>(child: U) => { result: { one: string; } & { two: string; } & U & U; deeper: <U extends Object>(child: U) => { result: { one: string; } & { two: string; } & U & U & U; deeper: <U extends Object>(child: U) => { result: { one: string; } & { two: string; } & U & U & U & U; deeper: <U extends Object>(child: U) => { result: { one: string; } & { two: string; } & U & U & U & U & U; deeper: <U extends Object>(child: U) => { result: { one: string; } & { two: string; } & U & U & U & U & U & U; deeper: <U extends Object>(child: U) => { result: { one: string; } & { two: string; } & U & U & U & U & U & U & U; deeper: <U extends Object>(child: U) => { result: { one: string; } & { two: string; } & U & U & U & U & U & U & U & U; deeper: <U extends Object>(child: U) => { result: { one: string; } & { two: string; } & U & U & U & U & U & U & U & U & U; deeper: <U extends Object>(child: U) => { result: { one: string; } & { two: string; } & U & U & U & U & U & U & U & U & U & U; deeper: <U extends Object>(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: <U extends Object>(child: U) => { result: { one: string; } & { two: string; } & U; deeper: <U extends Object>(child: U) => { result: { one: string; } & { two: string; } & U & U; deeper: <U extends Object>(child: U) => { result: { one: string; } & { two: string; } & U & U & U; deeper: <U extends Object>(child: U) => { result: { one: string; } & { two: string; } & U & U & U & U; deeper: <U extends Object>(child: U) => { result: { one: string; } & { two: string; } & U & U & U & U & U; deeper: <U extends Object>(child: U) => { result: { one: string; } & { two: string; } & U & U & U & U & U & U; deeper: <U extends Object>(child: U) => { result: { one: string; } & { two: string; } & U & U & U & U & U & U & U; deeper: <U extends Object>(child: U) => { result: { one: string; } & { two: string; } & U & U & U & U & U & U & U & U; deeper: <U extends Object>(child: U) => { result: { one: string; } & { two: string; } & U & U & U & U & U & U & U & U & U; deeper: <U extends Object>(child: U) => { result: { one: string; } & { two: string; } & U & U & U & U & U & U & U & U & U & U; deeper: <U extends Object>(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: <U extends Object>(child: U) => { result: { one: string; } & { two: string; } & { three: string; } & U; deeper: <U extends Object>(child: U) => { result: { one: string; } & { two: string; } & { three: string; } & U & U; deeper: <U extends Object>(child: U) => { result: { one: string; } & { two: string; } & { three: string; } & U & U & U; deeper: <U extends Object>(child: U) => { result: { one: string; } & { two: string; } & { three: string; } & U & U & U & U; deeper: <U extends Object>(child: U) => { result: { one: string; } & { two: string; } & { three: string; } & U & U & U & U & U; deeper: <U extends Object>(child: U) => { result: { one: string; } & { two: string; } & { three: string; } & U & U & U & U & U & U; deeper: <U extends Object>(child: U) => { result: { one: string; } & { two: string; } & { three: string; } & U & U & U & U & U & U & U; deeper: <U extends Object>(child: U) => { result: { one: string; } & { two: string; } & { three: string; } & U & U & U & U & U & U & U & U; deeper: <U extends Object>(child: U) => { result: { one: string; } & { two: string; } & { three: string; } & U & U & U & U & U & U & U & U & U; deeper: <U extends Object>(child: U) => { result: { one: string; } & { two: string; } & { three: string; } & U & U & U & U & U & U & U & U & U & U; deeper: <U extends Object>(child: U) => any; }; }; }; }; }; }; }; }; }; }; }
>p2.deeper({ three: '3' }) : { result: { one: string; } & { two: string; } & { three: string; }; deeper: <U extends Object>(child: U) => { result: { one: string; } & { two: string; } & { three: string; } & U; deeper: <U extends Object>(child: U) => { result: { one: string; } & { two: string; } & { three: string; } & U & U; deeper: <U extends Object>(child: U) => { result: { one: string; } & { two: string; } & { three: string; } & U & U & U; deeper: <U extends Object>(child: U) => { result: { one: string; } & { two: string; } & { three: string; } & U & U & U & U; deeper: <U extends Object>(child: U) => { result: { one: string; } & { two: string; } & { three: string; } & U & U & U & U & U; deeper: <U extends Object>(child: U) => { result: { one: string; } & { two: string; } & { three: string; } & U & U & U & U & U & U; deeper: <U extends Object>(child: U) => { result: { one: string; } & { two: string; } & { three: string; } & U & U & U & U & U & U & U; deeper: <U extends Object>(child: U) => { result: { one: string; } & { two: string; } & { three: string; } & U & U & U & U & U & U & U & U; deeper: <U extends Object>(child: U) => { result: { one: string; } & { two: string; } & { three: string; } & U & U & U & U & U & U & U & U & U; deeper: <U extends Object>(child: U) => { result: { one: string; } & { two: string; } & { three: string; } & U & U & U & U & U & U & U & U & U & U; deeper: <U extends Object>(child: U) => any; }; }; }; }; }; }; }; }; }; }; }
>p2.deeper : <U extends Object>(child: U) => { result: { one: string; } & { two: string; } & U; deeper: <U extends Object>(child: U) => { result: { one: string; } & { two: string; } & U & U; deeper: <U extends Object>(child: U) => { result: { one: string; } & { two: string; } & U & U & U; deeper: <U extends Object>(child: U) => { result: { one: string; } & { two: string; } & U & U & U & U; deeper: <U extends Object>(child: U) => { result: { one: string; } & { two: string; } & U & U & U & U & U; deeper: <U extends Object>(child: U) => { result: { one: string; } & { two: string; } & U & U & U & U & U & U; deeper: <U extends Object>(child: U) => { result: { one: string; } & { two: string; } & U & U & U & U & U & U & U; deeper: <U extends Object>(child: U) => { result: { one: string; } & { two: string; } & U & U & U & U & U & U & U & U; deeper: <U extends Object>(child: U) => { result: { one: string; } & { two: string; } & U & U & U & U & U & U & U & U & U; deeper: <U extends Object>(child: U) => { result: { one: string; } & { two: string; } & U & U & U & U & U & U & U & U & U & U; deeper: <U extends Object>(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: <U extends Object>(child: U) => { result: { one: string; } & { two: string; } & U; deeper: <U extends Object>(child: U) => { result: { one: string; } & { two: string; } & U & U; deeper: <U extends Object>(child: U) => { result: { one: string; } & { two: string; } & U & U & U; deeper: <U extends Object>(child: U) => { result: { one: string; } & { two: string; } & U & U & U & U; deeper: <U extends Object>(child: U) => { result: { one: string; } & { two: string; } & U & U & U & U & U; deeper: <U extends Object>(child: U) => { result: { one: string; } & { two: string; } & U & U & U & U & U & U; deeper: <U extends Object>(child: U) => { result: { one: string; } & { two: string; } & U & U & U & U & U & U & U; deeper: <U extends Object>(child: U) => { result: { one: string; } & { two: string; } & U & U & U & U & U & U & U & U; deeper: <U extends Object>(child: U) => { result: { one: string; } & { two: string; } & U & U & U & U & U & U & U & U & U; deeper: <U extends Object>(child: U) => { result: { one: string; } & { two: string; } & U & U & U & U & U & U & U & U & U & U; deeper: <U extends Object>(child: U) => any; }; }; }; }; }; }; }; }; }; }; }
>deeper : <U extends Object>(child: U) => { result: { one: string; } & { two: string; } & U; deeper: <U extends Object>(child: U) => { result: { one: string; } & { two: string; } & U & U; deeper: <U extends Object>(child: U) => { result: { one: string; } & { two: string; } & U & U & U; deeper: <U extends Object>(child: U) => { result: { one: string; } & { two: string; } & U & U & U & U; deeper: <U extends Object>(child: U) => { result: { one: string; } & { two: string; } & U & U & U & U & U; deeper: <U extends Object>(child: U) => { result: { one: string; } & { two: string; } & U & U & U & U & U & U; deeper: <U extends Object>(child: U) => { result: { one: string; } & { two: string; } & U & U & U & U & U & U & U; deeper: <U extends Object>(child: U) => { result: { one: string; } & { two: string; } & U & U & U & U & U & U & U & U; deeper: <U extends Object>(child: U) => { result: { one: string; } & { two: string; } & U & U & U & U & U & U & U & U & U; deeper: <U extends Object>(child: U) => { result: { one: string; } & { two: string; } & U & U & U & U & U & U & U & U & U & U; deeper: <U extends Object>(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: <U extends Object>(child: U) => { result: { one: string; } & { two: string; } & { three: string; } & U; deeper: <U extends Object>(child: U) => { result: { one: string; } & { two: string; } & { three: string; } & U & U; deeper: <U extends Object>(child: U) => { result: { one: string; } & { two: string; } & { three: string; } & U & U & U; deeper: <U extends Object>(child: U) => { result: { one: string; } & { two: string; } & { three: string; } & U & U & U & U; deeper: <U extends Object>(child: U) => { result: { one: string; } & { two: string; } & { three: string; } & U & U & U & U & U; deeper: <U extends Object>(child: U) => { result: { one: string; } & { two: string; } & { three: string; } & U & U & U & U & U & U; deeper: <U extends Object>(child: U) => { result: { one: string; } & { two: string; } & { three: string; } & U & U & U & U & U & U & U; deeper: <U extends Object>(child: U) => { result: { one: string; } & { two: string; } & { three: string; } & U & U & U & U & U & U & U & U; deeper: <U extends Object>(child: U) => { result: { one: string; } & { two: string; } & { three: string; } & U & U & U & U & U & U & U & U & U; deeper: <U extends Object>(child: U) => { result: { one: string; } & { two: string; } & { three: string; } & U & U & U & U & U & U & U & U & U & U; deeper: <U extends Object>(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: <U extends Object>(child: U) => { result: { one: string; } & { two: string; } & { three: string; } & U; deeper: <U extends Object>(child: U) => { result: { one: string; } & { two: string; } & { three: string; } & U & U; deeper: <U extends Object>(child: U) => { result: { one: string; } & { two: string; } & { three: string; } & U & U & U; deeper: <U extends Object>(child: U) => { result: { one: string; } & { two: string; } & { three: string; } & U & U & U & U; deeper: <U extends Object>(child: U) => { result: { one: string; } & { two: string; } & { three: string; } & U & U & U & U & U; deeper: <U extends Object>(child: U) => { result: { one: string; } & { two: string; } & { three: string; } & U & U & U & U & U & U; deeper: <U extends Object>(child: U) => { result: { one: string; } & { two: string; } & { three: string; } & U & U & U & U & U & U & U; deeper: <U extends Object>(child: U) => { result: { one: string; } & { two: string; } & { three: string; } & U & U & U & U & U & U & U & U; deeper: <U extends Object>(child: U) => { result: { one: string; } & { two: string; } & { three: string; } & U & U & U & U & U & U & U & U & U; deeper: <U extends Object>(child: U) => { result: { one: string; } & { two: string; } & { three: string; } & U & U & U & U & U & U & U & U & U & U; deeper: <U extends Object>(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: <U extends Object>(child: U) => { result: { one: string; } & { two: string; } & { three: string; } & U; deeper: <U extends Object>(child: U) => { result: { one: string; } & { two: string; } & { three: string; } & U & U; deeper: <U extends Object>(child: U) => { result: { one: string; } & { two: string; } & { three: string; } & U & U & U; deeper: <U extends Object>(child: U) => { result: { one: string; } & { two: string; } & { three: string; } & U & U & U & U; deeper: <U extends Object>(child: U) => { result: { one: string; } & { two: string; } & { three: string; } & U & U & U & U & U; deeper: <U extends Object>(child: U) => { result: { one: string; } & { two: string; } & { three: string; } & U & U & U & U & U & U; deeper: <U extends Object>(child: U) => { result: { one: string; } & { two: string; } & { three: string; } & U & U & U & U & U & U & U; deeper: <U extends Object>(child: U) => { result: { one: string; } & { two: string; } & { three: string; } & U & U & U & U & U & U & U & U; deeper: <U extends Object>(child: U) => { result: { one: string; } & { two: string; } & { three: string; } & U & U & U & U & U & U & U & U & U; deeper: <U extends Object>(child: U) => { result: { one: string; } & { two: string; } & { three: string; } & U & U & U & U & U & U & U & U & U & U; deeper: <U extends Object>(child: U) => any; }; }; }; }; }; }; }; }; }; }; }
>result : { one: string; } & { two: string; } & { three: string; }
>three : string

View File

@ -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<U> = keyof U;
export type Value<K extends Key<U>, U> = U[K];
export const updateIfChanged = <T>(t: T) => {
const reduce = <U>(u: U, update: (u: U) => T) => {
const set = (newU: U) => Object.is(u, newU) ? t : update(newU);
return Object.assign(
<K extends Key<U>>(key: K) =>
reduce<Value<K, U>>(u[key as keyof U] as Value<K, U>, (v: Value<K, U>) => {
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);
};
// example from https://github.com/microsoft/TypeScript/issues/31605
export const testRecFun = <T extends Object>(parent: T) => {
return {
result: parent,
deeper: <U extends Object>(child: U) =>
testRecFun<T & U>({ ...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;