From 9d17b345b4ba58156c7dcfe23e12c123efe69b04 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mateusz=20Burzy=C5=84ski?= Date: Mon, 12 Jun 2023 19:09:07 +0200 Subject: [PATCH] Revert collecting only outermost intra expression inference sites (#54613) --- src/compiler/checker.ts | 37 +- .../intraExpressionInferences.errors.txt | 119 ++++- .../reference/intraExpressionInferences.js | 228 +++++++++- .../intraExpressionInferences.symbols | 406 +++++++++++++++++ .../reference/intraExpressionInferences.types | 414 ++++++++++++++++++ .../intraExpressionInferences.ts | 118 ++++- 6 files changed, 1295 insertions(+), 27 deletions(-) diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 8e148c857e86e..4eb2db0bd29e8 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -1254,13 +1254,12 @@ export const enum CheckMode { Inferential = 1 << 1, // Inferential typing SkipContextSensitive = 1 << 2, // Skip context sensitive function expressions SkipGenericFunctions = 1 << 3, // Skip single signature generic functions - SkipAddingIntraExpressionSites = 1 << 4, // Skip adding intra expression sites in nested expressions since only the outermost one has to be added - IsForSignatureHelp = 1 << 5, // Call resolution for purposes of signature help - IsForStringLiteralArgumentCompletions = 1 << 6, // Do not infer from the argument currently being typed - RestBindingElement = 1 << 7, // Checking a type that is going to be used to determine the type of a rest binding element + IsForSignatureHelp = 1 << 4, // Call resolution for purposes of signature help + IsForStringLiteralArgumentCompletions = 1 << 5, // Do not infer from the argument currently being typed + RestBindingElement = 1 << 6, // Checking a type that is going to be used to determine the type of a rest binding element // e.g. in `const { a, ...rest } = foo`, when checking the type of `foo` to determine the type of `rest`, // we need to preserve generic types instead of substituting them for constraints - TypeOnly = 1 << 8, // Called from getTypeOfExpression, diagnostics may be omitted + TypeOnly = 1 << 7, // Called from getTypeOfExpression, diagnostics may be omitted } /** @internal */ @@ -29990,13 +29989,10 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { elementFlags.push(ElementFlags.Optional); } else { - const shouldAddAsIntraExpressionInferenceSite = inTupleContext && checkMode && checkMode & CheckMode.Inferential && !(checkMode & (CheckMode.SkipContextSensitive | CheckMode.SkipAddingIntraExpressionSites)) && isContextSensitive(e); - const elementCheckMode = (checkMode || CheckMode.Normal) | (shouldAddAsIntraExpressionInferenceSite ? CheckMode.SkipAddingIntraExpressionSites : 0); - - const type = checkExpressionForMutableLocation(e, elementCheckMode, forceTuple); + const type = checkExpressionForMutableLocation(e, checkMode, forceTuple); elementTypes.push(addOptionality(type, /*isProperty*/ true, hasOmittedExpression)); elementFlags.push(hasOmittedExpression ? ElementFlags.Optional : ElementFlags.Required); - if (shouldAddAsIntraExpressionInferenceSite) { + if (inTupleContext && checkMode && checkMode & CheckMode.Inferential && !(checkMode & CheckMode.SkipContextSensitive) && isContextSensitive(e)) { const inferenceContext = getInferenceContext(node); Debug.assert(inferenceContext); // In CheckMode.Inferential we should always have an inference context addIntraExpressionInferenceSite(inferenceContext, e, type); @@ -30161,17 +30157,12 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { if (memberDecl.kind === SyntaxKind.PropertyAssignment || memberDecl.kind === SyntaxKind.ShorthandPropertyAssignment || isObjectLiteralMethod(memberDecl)) { - - const shouldAddAsIntraExpressionInferenceSite = contextualType && checkMode & CheckMode.Inferential && !(checkMode & (CheckMode.SkipContextSensitive | CheckMode.SkipAddingIntraExpressionSites)) && - (memberDecl.kind === SyntaxKind.PropertyAssignment || memberDecl.kind === SyntaxKind.MethodDeclaration) && isContextSensitive(memberDecl); - const propCheckMode = checkMode | (shouldAddAsIntraExpressionInferenceSite ? CheckMode.SkipAddingIntraExpressionSites : 0); - - let type = memberDecl.kind === SyntaxKind.PropertyAssignment ? checkPropertyAssignment(memberDecl, propCheckMode) : + let type = memberDecl.kind === SyntaxKind.PropertyAssignment ? checkPropertyAssignment(memberDecl, checkMode) : // avoid resolving the left side of the ShorthandPropertyAssignment outside of the destructuring // for error recovery purposes. For example, if a user wrote `{ a = 100 }` instead of `{ a: 100 }`. // we don't want to say "could not find 'a'". - memberDecl.kind === SyntaxKind.ShorthandPropertyAssignment ? checkExpressionForMutableLocation(!inDestructuringPattern && memberDecl.objectAssignmentInitializer ? memberDecl.objectAssignmentInitializer : memberDecl.name, propCheckMode) : - checkObjectLiteralMethod(memberDecl, propCheckMode); + memberDecl.kind === SyntaxKind.ShorthandPropertyAssignment ? checkExpressionForMutableLocation(!inDestructuringPattern && memberDecl.objectAssignmentInitializer ? memberDecl.objectAssignmentInitializer : memberDecl.name, checkMode) : + checkObjectLiteralMethod(memberDecl, checkMode); if (isInJavascript) { const jsDocType = getTypeForDeclarationFromJSDocComment(memberDecl); if (jsDocType) { @@ -30226,7 +30217,8 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { member = prop; allPropertiesTable?.set(prop.escapedName, prop); - if (shouldAddAsIntraExpressionInferenceSite) { + if (contextualType && checkMode & CheckMode.Inferential && !(checkMode & CheckMode.SkipContextSensitive) && + (memberDecl.kind === SyntaxKind.PropertyAssignment || memberDecl.kind === SyntaxKind.MethodDeclaration) && isContextSensitive(memberDecl)) { const inferenceContext = getInferenceContext(node); Debug.assert(inferenceContext); // In CheckMode.Inferential we should always have an inference context const inferenceNode = memberDecl.kind === SyntaxKind.PropertyAssignment ? memberDecl.initializer : memberDecl; @@ -30460,10 +30452,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { for (const attributeDecl of attributes.properties) { const member = attributeDecl.symbol; if (isJsxAttribute(attributeDecl)) { - const shouldAddAsIntraExpressionInferenceSite = contextualType && checkMode & CheckMode.Inferential && !(checkMode & (CheckMode.SkipContextSensitive | CheckMode.SkipAddingIntraExpressionSites)) && isContextSensitive(attributeDecl); - const attributeCheckMode = checkMode | (shouldAddAsIntraExpressionInferenceSite ? CheckMode.SkipAddingIntraExpressionSites : 0); - - const exprType = checkJsxAttribute(attributeDecl, attributeCheckMode); + const exprType = checkJsxAttribute(attributeDecl, checkMode); objectFlags |= getObjectFlags(exprType) & ObjectFlags.PropagatingFlags; const attributeSymbol = createSymbol(SymbolFlags.Property | member.flags, member.escapedName); @@ -30485,7 +30474,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { addDeprecatedSuggestion(attributeDecl.name, prop.declarations, attributeDecl.name.escapedText as string); } } - if (shouldAddAsIntraExpressionInferenceSite) { + if (contextualType && checkMode & CheckMode.Inferential && !(checkMode & CheckMode.SkipContextSensitive) && isContextSensitive(attributeDecl)) { const inferenceContext = getInferenceContext(attributes); Debug.assert(inferenceContext); // In CheckMode.Inferential we should always have an inference context const inferenceNode = (attributeDecl.initializer as JsxExpression).expression!; diff --git a/tests/baselines/reference/intraExpressionInferences.errors.txt b/tests/baselines/reference/intraExpressionInferences.errors.txt index 87998f166d935..82da18c788e9b 100644 --- a/tests/baselines/reference/intraExpressionInferences.errors.txt +++ b/tests/baselines/reference/intraExpressionInferences.errors.txt @@ -227,4 +227,121 @@ intraExpressionInferences.ts(133,26): error TS2339: Property 'nonexistent' does arg.toString(); }, }, - }); \ No newline at end of file + }); + + declare function nested(arg: { + prop: { + produce: (arg1: number) => T; + consume: (arg2: T) => void; + }; + }): T; + + const resNested = nested({ + prop: { + produce: (a) => [a], + consume: (arg) => arg.join(","), + }, + }); + + declare function twoConsumers(arg: { + a: (arg: string) => T; + consume1: (arg1: T) => void; + consume2: (arg2: T) => void; + }): T; + + const resTwoConsumers = twoConsumers({ + a: (arg) => [arg], + consume1: (arg1) => {}, + consume2: (arg2) => {}, + }); + + declare function multipleProducersBeforeConsumers(arg: { + a: (arg: string) => T; + b: (arg: string) => T2; + consume1: (arg1: T) => void; + consume2: (arg2: T2) => void; + }): [T, T2]; + + const resMultipleProducersBeforeConsumers = multipleProducersBeforeConsumers({ + a: (arg) => [arg], + b: (arg) => Number(arg), + consume1: (arg1) => {}, + consume2: (arg2) => {}, + }); + + declare function withConditionalExpression(arg: { + a: (arg1: string) => T; + b: (arg2: T) => T2; + c: (arg2: T2) => T3; + }): [T, T2, T3]; + + const resWithConditionalExpression = withConditionalExpression({ + a: (arg) => [arg], + b: Math.random() ? (arg) => "first" as const : (arg) => "two" as const, + c: (arg) => Boolean(arg), + }); + + declare function onion(arg: { + a: (arg1: string) => T; + nested: { + b: (arg2: T) => T2; + nested2: { + c: (arg2: T2) => T3; + }; + }; + }): [T, T2, T3]; + + const resOnion = onion({ + a: (arg) => [arg], + nested: { + b: (arg) => arg.join(","), + nested2: { + c: (arg) => Boolean(arg), + }, + }, + }); + + declare function onion2(arg: { + a: (arg1: string) => T; + nested: { + b: (arg2: T) => T2; + c: (arg3: T) => T3; + nested2: { + d: (arg4: T3) => T4; + }; + }; + }): [T, T2, T3, T4]; + + const resOnion2 = onion2({ + a: (arg) => [arg], + nested: { + b: (arg) => arg.join(","), + c: (arg) => Number(arg), + nested2: { + d: (arg) => Boolean(arg), + }, + }, + }); + + declare function distant(args: { + foo: { + bar: { + baz: { + producer: (arg: string) => T; + }; + }; + }; + consumer: (val: T) => unknown; + }): T; + + const distantRes = distant({ + foo: { + bar: { + baz: { + producer: (arg) => 1, + }, + }, + }, + consumer: (val) => {}, + }); + \ No newline at end of file diff --git a/tests/baselines/reference/intraExpressionInferences.js b/tests/baselines/reference/intraExpressionInferences.js index 995c8145b3d06..fbdd0e64bd30e 100644 --- a/tests/baselines/reference/intraExpressionInferences.js +++ b/tests/baselines/reference/intraExpressionInferences.js @@ -214,7 +214,124 @@ Foo({ arg.toString(); }, }, -}); +}); + +declare function nested(arg: { + prop: { + produce: (arg1: number) => T; + consume: (arg2: T) => void; + }; +}): T; + +const resNested = nested({ + prop: { + produce: (a) => [a], + consume: (arg) => arg.join(","), + }, +}); + +declare function twoConsumers(arg: { + a: (arg: string) => T; + consume1: (arg1: T) => void; + consume2: (arg2: T) => void; +}): T; + +const resTwoConsumers = twoConsumers({ + a: (arg) => [arg], + consume1: (arg1) => {}, + consume2: (arg2) => {}, +}); + +declare function multipleProducersBeforeConsumers(arg: { + a: (arg: string) => T; + b: (arg: string) => T2; + consume1: (arg1: T) => void; + consume2: (arg2: T2) => void; +}): [T, T2]; + +const resMultipleProducersBeforeConsumers = multipleProducersBeforeConsumers({ + a: (arg) => [arg], + b: (arg) => Number(arg), + consume1: (arg1) => {}, + consume2: (arg2) => {}, +}); + +declare function withConditionalExpression(arg: { + a: (arg1: string) => T; + b: (arg2: T) => T2; + c: (arg2: T2) => T3; +}): [T, T2, T3]; + +const resWithConditionalExpression = withConditionalExpression({ + a: (arg) => [arg], + b: Math.random() ? (arg) => "first" as const : (arg) => "two" as const, + c: (arg) => Boolean(arg), +}); + +declare function onion(arg: { + a: (arg1: string) => T; + nested: { + b: (arg2: T) => T2; + nested2: { + c: (arg2: T2) => T3; + }; + }; +}): [T, T2, T3]; + +const resOnion = onion({ + a: (arg) => [arg], + nested: { + b: (arg) => arg.join(","), + nested2: { + c: (arg) => Boolean(arg), + }, + }, +}); + +declare function onion2(arg: { + a: (arg1: string) => T; + nested: { + b: (arg2: T) => T2; + c: (arg3: T) => T3; + nested2: { + d: (arg4: T3) => T4; + }; + }; +}): [T, T2, T3, T4]; + +const resOnion2 = onion2({ + a: (arg) => [arg], + nested: { + b: (arg) => arg.join(","), + c: (arg) => Number(arg), + nested2: { + d: (arg) => Boolean(arg), + }, + }, +}); + +declare function distant(args: { + foo: { + bar: { + baz: { + producer: (arg: string) => T; + }; + }; + }; + consumer: (val: T) => unknown; +}): T; + +const distantRes = distant({ + foo: { + bar: { + baz: { + producer: (arg) => 1, + }, + }, + }, + consumer: (val) => {}, +}); + //// [intraExpressionInferences.js] "use strict"; @@ -350,6 +467,57 @@ Foo(__assign({ arg.toString(); }, })); +var resNested = nested({ + prop: { + produce: function (a) { return [a]; }, + consume: function (arg) { return arg.join(","); }, + }, +}); +var resTwoConsumers = twoConsumers({ + a: function (arg) { return [arg]; }, + consume1: function (arg1) { }, + consume2: function (arg2) { }, +}); +var resMultipleProducersBeforeConsumers = multipleProducersBeforeConsumers({ + a: function (arg) { return [arg]; }, + b: function (arg) { return Number(arg); }, + consume1: function (arg1) { }, + consume2: function (arg2) { }, +}); +var resWithConditionalExpression = withConditionalExpression({ + a: function (arg) { return [arg]; }, + b: Math.random() ? function (arg) { return "first"; } : function (arg) { return "two"; }, + c: function (arg) { return Boolean(arg); }, +}); +var resOnion = onion({ + a: function (arg) { return [arg]; }, + nested: { + b: function (arg) { return arg.join(","); }, + nested2: { + c: function (arg) { return Boolean(arg); }, + }, + }, +}); +var resOnion2 = onion2({ + a: function (arg) { return [arg]; }, + nested: { + b: function (arg) { return arg.join(","); }, + c: function (arg) { return Number(arg); }, + nested2: { + d: function (arg) { return Boolean(arg); }, + }, + }, +}); +var distantRes = distant({ + foo: { + bar: { + baz: { + producer: function (arg) { return 1; }, + }, + }, + }, + consumer: function (val) { }, +}); //// [intraExpressionInferences.d.ts] @@ -422,3 +590,61 @@ interface Props { b: (arg: T) => void; } declare function Foo(props: Props): null; +declare function nested(arg: { + prop: { + produce: (arg1: number) => T; + consume: (arg2: T) => void; + }; +}): T; +declare const resNested: number[]; +declare function twoConsumers(arg: { + a: (arg: string) => T; + consume1: (arg1: T) => void; + consume2: (arg2: T) => void; +}): T; +declare const resTwoConsumers: string[]; +declare function multipleProducersBeforeConsumers(arg: { + a: (arg: string) => T; + b: (arg: string) => T2; + consume1: (arg1: T) => void; + consume2: (arg2: T2) => void; +}): [T, T2]; +declare const resMultipleProducersBeforeConsumers: [string[], number]; +declare function withConditionalExpression(arg: { + a: (arg1: string) => T; + b: (arg2: T) => T2; + c: (arg2: T2) => T3; +}): [T, T2, T3]; +declare const resWithConditionalExpression: [string[], "first" | "two", boolean]; +declare function onion(arg: { + a: (arg1: string) => T; + nested: { + b: (arg2: T) => T2; + nested2: { + c: (arg2: T2) => T3; + }; + }; +}): [T, T2, T3]; +declare const resOnion: [string[], string, boolean]; +declare function onion2(arg: { + a: (arg1: string) => T; + nested: { + b: (arg2: T) => T2; + c: (arg3: T) => T3; + nested2: { + d: (arg4: T3) => T4; + }; + }; +}): [T, T2, T3, T4]; +declare const resOnion2: [string[], string, number, boolean]; +declare function distant(args: { + foo: { + bar: { + baz: { + producer: (arg: string) => T; + }; + }; + }; + consumer: (val: T) => unknown; +}): T; +declare const distantRes: number; diff --git a/tests/baselines/reference/intraExpressionInferences.symbols b/tests/baselines/reference/intraExpressionInferences.symbols index 92356d1961cc6..f0a01515373d5 100644 --- a/tests/baselines/reference/intraExpressionInferences.symbols +++ b/tests/baselines/reference/intraExpressionInferences.symbols @@ -670,3 +670,409 @@ Foo({ }, }, }); + +declare function nested(arg: { +>nested : Symbol(nested, Decl(intraExpressionInferences.ts, 213, 3)) +>T : Symbol(T, Decl(intraExpressionInferences.ts, 215, 24)) +>arg : Symbol(arg, Decl(intraExpressionInferences.ts, 215, 27)) + + prop: { +>prop : Symbol(prop, Decl(intraExpressionInferences.ts, 215, 33)) + + produce: (arg1: number) => T; +>produce : Symbol(produce, Decl(intraExpressionInferences.ts, 216, 9)) +>arg1 : Symbol(arg1, Decl(intraExpressionInferences.ts, 217, 14)) +>T : Symbol(T, Decl(intraExpressionInferences.ts, 215, 24)) + + consume: (arg2: T) => void; +>consume : Symbol(consume, Decl(intraExpressionInferences.ts, 217, 33)) +>arg2 : Symbol(arg2, Decl(intraExpressionInferences.ts, 218, 14)) +>T : Symbol(T, Decl(intraExpressionInferences.ts, 215, 24)) + + }; +}): T; +>T : Symbol(T, Decl(intraExpressionInferences.ts, 215, 24)) + +const resNested = nested({ +>resNested : Symbol(resNested, Decl(intraExpressionInferences.ts, 222, 5)) +>nested : Symbol(nested, Decl(intraExpressionInferences.ts, 213, 3)) + + prop: { +>prop : Symbol(prop, Decl(intraExpressionInferences.ts, 222, 26)) + + produce: (a) => [a], +>produce : Symbol(produce, Decl(intraExpressionInferences.ts, 223, 9)) +>a : Symbol(a, Decl(intraExpressionInferences.ts, 224, 14)) +>a : Symbol(a, Decl(intraExpressionInferences.ts, 224, 14)) + + consume: (arg) => arg.join(","), +>consume : Symbol(consume, Decl(intraExpressionInferences.ts, 224, 24)) +>arg : Symbol(arg, Decl(intraExpressionInferences.ts, 225, 14)) +>arg.join : Symbol(Array.join, Decl(lib.es5.d.ts, --, --)) +>arg : Symbol(arg, Decl(intraExpressionInferences.ts, 225, 14)) +>join : Symbol(Array.join, Decl(lib.es5.d.ts, --, --)) + + }, +}); + +declare function twoConsumers(arg: { +>twoConsumers : Symbol(twoConsumers, Decl(intraExpressionInferences.ts, 227, 3)) +>T : Symbol(T, Decl(intraExpressionInferences.ts, 229, 30)) +>arg : Symbol(arg, Decl(intraExpressionInferences.ts, 229, 33)) + + a: (arg: string) => T; +>a : Symbol(a, Decl(intraExpressionInferences.ts, 229, 39)) +>arg : Symbol(arg, Decl(intraExpressionInferences.ts, 230, 6)) +>T : Symbol(T, Decl(intraExpressionInferences.ts, 229, 30)) + + consume1: (arg1: T) => void; +>consume1 : Symbol(consume1, Decl(intraExpressionInferences.ts, 230, 24)) +>arg1 : Symbol(arg1, Decl(intraExpressionInferences.ts, 231, 13)) +>T : Symbol(T, Decl(intraExpressionInferences.ts, 229, 30)) + + consume2: (arg2: T) => void; +>consume2 : Symbol(consume2, Decl(intraExpressionInferences.ts, 231, 30)) +>arg2 : Symbol(arg2, Decl(intraExpressionInferences.ts, 232, 13)) +>T : Symbol(T, Decl(intraExpressionInferences.ts, 229, 30)) + +}): T; +>T : Symbol(T, Decl(intraExpressionInferences.ts, 229, 30)) + +const resTwoConsumers = twoConsumers({ +>resTwoConsumers : Symbol(resTwoConsumers, Decl(intraExpressionInferences.ts, 235, 5)) +>twoConsumers : Symbol(twoConsumers, Decl(intraExpressionInferences.ts, 227, 3)) + + a: (arg) => [arg], +>a : Symbol(a, Decl(intraExpressionInferences.ts, 235, 38)) +>arg : Symbol(arg, Decl(intraExpressionInferences.ts, 236, 6)) +>arg : Symbol(arg, Decl(intraExpressionInferences.ts, 236, 6)) + + consume1: (arg1) => {}, +>consume1 : Symbol(consume1, Decl(intraExpressionInferences.ts, 236, 20)) +>arg1 : Symbol(arg1, Decl(intraExpressionInferences.ts, 237, 13)) + + consume2: (arg2) => {}, +>consume2 : Symbol(consume2, Decl(intraExpressionInferences.ts, 237, 25)) +>arg2 : Symbol(arg2, Decl(intraExpressionInferences.ts, 238, 13)) + +}); + +declare function multipleProducersBeforeConsumers(arg: { +>multipleProducersBeforeConsumers : Symbol(multipleProducersBeforeConsumers, Decl(intraExpressionInferences.ts, 239, 3)) +>T : Symbol(T, Decl(intraExpressionInferences.ts, 241, 50)) +>T2 : Symbol(T2, Decl(intraExpressionInferences.ts, 241, 52)) +>arg : Symbol(arg, Decl(intraExpressionInferences.ts, 241, 57)) + + a: (arg: string) => T; +>a : Symbol(a, Decl(intraExpressionInferences.ts, 241, 63)) +>arg : Symbol(arg, Decl(intraExpressionInferences.ts, 242, 6)) +>T : Symbol(T, Decl(intraExpressionInferences.ts, 241, 50)) + + b: (arg: string) => T2; +>b : Symbol(b, Decl(intraExpressionInferences.ts, 242, 24)) +>arg : Symbol(arg, Decl(intraExpressionInferences.ts, 243, 6)) +>T2 : Symbol(T2, Decl(intraExpressionInferences.ts, 241, 52)) + + consume1: (arg1: T) => void; +>consume1 : Symbol(consume1, Decl(intraExpressionInferences.ts, 243, 25)) +>arg1 : Symbol(arg1, Decl(intraExpressionInferences.ts, 244, 13)) +>T : Symbol(T, Decl(intraExpressionInferences.ts, 241, 50)) + + consume2: (arg2: T2) => void; +>consume2 : Symbol(consume2, Decl(intraExpressionInferences.ts, 244, 30)) +>arg2 : Symbol(arg2, Decl(intraExpressionInferences.ts, 245, 13)) +>T2 : Symbol(T2, Decl(intraExpressionInferences.ts, 241, 52)) + +}): [T, T2]; +>T : Symbol(T, Decl(intraExpressionInferences.ts, 241, 50)) +>T2 : Symbol(T2, Decl(intraExpressionInferences.ts, 241, 52)) + +const resMultipleProducersBeforeConsumers = multipleProducersBeforeConsumers({ +>resMultipleProducersBeforeConsumers : Symbol(resMultipleProducersBeforeConsumers, Decl(intraExpressionInferences.ts, 248, 5)) +>multipleProducersBeforeConsumers : Symbol(multipleProducersBeforeConsumers, Decl(intraExpressionInferences.ts, 239, 3)) + + a: (arg) => [arg], +>a : Symbol(a, Decl(intraExpressionInferences.ts, 248, 78)) +>arg : Symbol(arg, Decl(intraExpressionInferences.ts, 249, 6)) +>arg : Symbol(arg, Decl(intraExpressionInferences.ts, 249, 6)) + + b: (arg) => Number(arg), +>b : Symbol(b, Decl(intraExpressionInferences.ts, 249, 20)) +>arg : Symbol(arg, Decl(intraExpressionInferences.ts, 250, 6)) +>Number : Symbol(Number, Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --)) +>arg : Symbol(arg, Decl(intraExpressionInferences.ts, 250, 6)) + + consume1: (arg1) => {}, +>consume1 : Symbol(consume1, Decl(intraExpressionInferences.ts, 250, 26)) +>arg1 : Symbol(arg1, Decl(intraExpressionInferences.ts, 251, 13)) + + consume2: (arg2) => {}, +>consume2 : Symbol(consume2, Decl(intraExpressionInferences.ts, 251, 25)) +>arg2 : Symbol(arg2, Decl(intraExpressionInferences.ts, 252, 13)) + +}); + +declare function withConditionalExpression(arg: { +>withConditionalExpression : Symbol(withConditionalExpression, Decl(intraExpressionInferences.ts, 253, 3)) +>T : Symbol(T, Decl(intraExpressionInferences.ts, 255, 43)) +>T2 : Symbol(T2, Decl(intraExpressionInferences.ts, 255, 45)) +>T3 : Symbol(T3, Decl(intraExpressionInferences.ts, 255, 49)) +>arg : Symbol(arg, Decl(intraExpressionInferences.ts, 255, 54)) + + a: (arg1: string) => T; +>a : Symbol(a, Decl(intraExpressionInferences.ts, 255, 60)) +>arg1 : Symbol(arg1, Decl(intraExpressionInferences.ts, 256, 6)) +>T : Symbol(T, Decl(intraExpressionInferences.ts, 255, 43)) + + b: (arg2: T) => T2; +>b : Symbol(b, Decl(intraExpressionInferences.ts, 256, 25)) +>arg2 : Symbol(arg2, Decl(intraExpressionInferences.ts, 257, 6)) +>T : Symbol(T, Decl(intraExpressionInferences.ts, 255, 43)) +>T2 : Symbol(T2, Decl(intraExpressionInferences.ts, 255, 45)) + + c: (arg2: T2) => T3; +>c : Symbol(c, Decl(intraExpressionInferences.ts, 257, 21)) +>arg2 : Symbol(arg2, Decl(intraExpressionInferences.ts, 258, 6)) +>T2 : Symbol(T2, Decl(intraExpressionInferences.ts, 255, 45)) +>T3 : Symbol(T3, Decl(intraExpressionInferences.ts, 255, 49)) + +}): [T, T2, T3]; +>T : Symbol(T, Decl(intraExpressionInferences.ts, 255, 43)) +>T2 : Symbol(T2, Decl(intraExpressionInferences.ts, 255, 45)) +>T3 : Symbol(T3, Decl(intraExpressionInferences.ts, 255, 49)) + +const resWithConditionalExpression = withConditionalExpression({ +>resWithConditionalExpression : Symbol(resWithConditionalExpression, Decl(intraExpressionInferences.ts, 261, 5)) +>withConditionalExpression : Symbol(withConditionalExpression, Decl(intraExpressionInferences.ts, 253, 3)) + + a: (arg) => [arg], +>a : Symbol(a, Decl(intraExpressionInferences.ts, 261, 64)) +>arg : Symbol(arg, Decl(intraExpressionInferences.ts, 262, 6)) +>arg : Symbol(arg, Decl(intraExpressionInferences.ts, 262, 6)) + + b: Math.random() ? (arg) => "first" as const : (arg) => "two" as const, +>b : Symbol(b, Decl(intraExpressionInferences.ts, 262, 20)) +>Math.random : Symbol(Math.random, Decl(lib.es5.d.ts, --, --)) +>Math : Symbol(Math, Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --)) +>random : Symbol(Math.random, Decl(lib.es5.d.ts, --, --)) +>arg : Symbol(arg, Decl(intraExpressionInferences.ts, 263, 22)) +>const : Symbol(const) +>arg : Symbol(arg, Decl(intraExpressionInferences.ts, 263, 50)) +>const : Symbol(const) + + c: (arg) => Boolean(arg), +>c : Symbol(c, Decl(intraExpressionInferences.ts, 263, 73)) +>arg : Symbol(arg, Decl(intraExpressionInferences.ts, 264, 6)) +>Boolean : Symbol(Boolean, Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --)) +>arg : Symbol(arg, Decl(intraExpressionInferences.ts, 264, 6)) + +}); + +declare function onion(arg: { +>onion : Symbol(onion, Decl(intraExpressionInferences.ts, 265, 3)) +>T : Symbol(T, Decl(intraExpressionInferences.ts, 267, 23)) +>T2 : Symbol(T2, Decl(intraExpressionInferences.ts, 267, 25)) +>T3 : Symbol(T3, Decl(intraExpressionInferences.ts, 267, 29)) +>arg : Symbol(arg, Decl(intraExpressionInferences.ts, 267, 34)) + + a: (arg1: string) => T; +>a : Symbol(a, Decl(intraExpressionInferences.ts, 267, 40)) +>arg1 : Symbol(arg1, Decl(intraExpressionInferences.ts, 268, 6)) +>T : Symbol(T, Decl(intraExpressionInferences.ts, 267, 23)) + + nested: { +>nested : Symbol(nested, Decl(intraExpressionInferences.ts, 268, 25)) + + b: (arg2: T) => T2; +>b : Symbol(b, Decl(intraExpressionInferences.ts, 269, 11)) +>arg2 : Symbol(arg2, Decl(intraExpressionInferences.ts, 270, 8)) +>T : Symbol(T, Decl(intraExpressionInferences.ts, 267, 23)) +>T2 : Symbol(T2, Decl(intraExpressionInferences.ts, 267, 25)) + + nested2: { +>nested2 : Symbol(nested2, Decl(intraExpressionInferences.ts, 270, 23)) + + c: (arg2: T2) => T3; +>c : Symbol(c, Decl(intraExpressionInferences.ts, 271, 14)) +>arg2 : Symbol(arg2, Decl(intraExpressionInferences.ts, 272, 10)) +>T2 : Symbol(T2, Decl(intraExpressionInferences.ts, 267, 25)) +>T3 : Symbol(T3, Decl(intraExpressionInferences.ts, 267, 29)) + + }; + }; +}): [T, T2, T3]; +>T : Symbol(T, Decl(intraExpressionInferences.ts, 267, 23)) +>T2 : Symbol(T2, Decl(intraExpressionInferences.ts, 267, 25)) +>T3 : Symbol(T3, Decl(intraExpressionInferences.ts, 267, 29)) + +const resOnion = onion({ +>resOnion : Symbol(resOnion, Decl(intraExpressionInferences.ts, 277, 5)) +>onion : Symbol(onion, Decl(intraExpressionInferences.ts, 265, 3)) + + a: (arg) => [arg], +>a : Symbol(a, Decl(intraExpressionInferences.ts, 277, 24)) +>arg : Symbol(arg, Decl(intraExpressionInferences.ts, 278, 6)) +>arg : Symbol(arg, Decl(intraExpressionInferences.ts, 278, 6)) + + nested: { +>nested : Symbol(nested, Decl(intraExpressionInferences.ts, 278, 20)) + + b: (arg) => arg.join(","), +>b : Symbol(b, Decl(intraExpressionInferences.ts, 279, 11)) +>arg : Symbol(arg, Decl(intraExpressionInferences.ts, 280, 8)) +>arg.join : Symbol(Array.join, Decl(lib.es5.d.ts, --, --)) +>arg : Symbol(arg, Decl(intraExpressionInferences.ts, 280, 8)) +>join : Symbol(Array.join, Decl(lib.es5.d.ts, --, --)) + + nested2: { +>nested2 : Symbol(nested2, Decl(intraExpressionInferences.ts, 280, 30)) + + c: (arg) => Boolean(arg), +>c : Symbol(c, Decl(intraExpressionInferences.ts, 281, 14)) +>arg : Symbol(arg, Decl(intraExpressionInferences.ts, 282, 10)) +>Boolean : Symbol(Boolean, Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --)) +>arg : Symbol(arg, Decl(intraExpressionInferences.ts, 282, 10)) + + }, + }, +}); + +declare function onion2(arg: { +>onion2 : Symbol(onion2, Decl(intraExpressionInferences.ts, 285, 3)) +>T : Symbol(T, Decl(intraExpressionInferences.ts, 287, 24)) +>T2 : Symbol(T2, Decl(intraExpressionInferences.ts, 287, 26)) +>T3 : Symbol(T3, Decl(intraExpressionInferences.ts, 287, 30)) +>T4 : Symbol(T4, Decl(intraExpressionInferences.ts, 287, 34)) +>arg : Symbol(arg, Decl(intraExpressionInferences.ts, 287, 39)) + + a: (arg1: string) => T; +>a : Symbol(a, Decl(intraExpressionInferences.ts, 287, 45)) +>arg1 : Symbol(arg1, Decl(intraExpressionInferences.ts, 288, 6)) +>T : Symbol(T, Decl(intraExpressionInferences.ts, 287, 24)) + + nested: { +>nested : Symbol(nested, Decl(intraExpressionInferences.ts, 288, 25)) + + b: (arg2: T) => T2; +>b : Symbol(b, Decl(intraExpressionInferences.ts, 289, 11)) +>arg2 : Symbol(arg2, Decl(intraExpressionInferences.ts, 290, 8)) +>T : Symbol(T, Decl(intraExpressionInferences.ts, 287, 24)) +>T2 : Symbol(T2, Decl(intraExpressionInferences.ts, 287, 26)) + + c: (arg3: T) => T3; +>c : Symbol(c, Decl(intraExpressionInferences.ts, 290, 23)) +>arg3 : Symbol(arg3, Decl(intraExpressionInferences.ts, 291, 8)) +>T : Symbol(T, Decl(intraExpressionInferences.ts, 287, 24)) +>T3 : Symbol(T3, Decl(intraExpressionInferences.ts, 287, 30)) + + nested2: { +>nested2 : Symbol(nested2, Decl(intraExpressionInferences.ts, 291, 23)) + + d: (arg4: T3) => T4; +>d : Symbol(d, Decl(intraExpressionInferences.ts, 292, 14)) +>arg4 : Symbol(arg4, Decl(intraExpressionInferences.ts, 293, 10)) +>T3 : Symbol(T3, Decl(intraExpressionInferences.ts, 287, 30)) +>T4 : Symbol(T4, Decl(intraExpressionInferences.ts, 287, 34)) + + }; + }; +}): [T, T2, T3, T4]; +>T : Symbol(T, Decl(intraExpressionInferences.ts, 287, 24)) +>T2 : Symbol(T2, Decl(intraExpressionInferences.ts, 287, 26)) +>T3 : Symbol(T3, Decl(intraExpressionInferences.ts, 287, 30)) +>T4 : Symbol(T4, Decl(intraExpressionInferences.ts, 287, 34)) + +const resOnion2 = onion2({ +>resOnion2 : Symbol(resOnion2, Decl(intraExpressionInferences.ts, 298, 5)) +>onion2 : Symbol(onion2, Decl(intraExpressionInferences.ts, 285, 3)) + + a: (arg) => [arg], +>a : Symbol(a, Decl(intraExpressionInferences.ts, 298, 26)) +>arg : Symbol(arg, Decl(intraExpressionInferences.ts, 299, 6)) +>arg : Symbol(arg, Decl(intraExpressionInferences.ts, 299, 6)) + + nested: { +>nested : Symbol(nested, Decl(intraExpressionInferences.ts, 299, 20)) + + b: (arg) => arg.join(","), +>b : Symbol(b, Decl(intraExpressionInferences.ts, 300, 11)) +>arg : Symbol(arg, Decl(intraExpressionInferences.ts, 301, 8)) +>arg.join : Symbol(Array.join, Decl(lib.es5.d.ts, --, --)) +>arg : Symbol(arg, Decl(intraExpressionInferences.ts, 301, 8)) +>join : Symbol(Array.join, Decl(lib.es5.d.ts, --, --)) + + c: (arg) => Number(arg), +>c : Symbol(c, Decl(intraExpressionInferences.ts, 301, 30)) +>arg : Symbol(arg, Decl(intraExpressionInferences.ts, 302, 8)) +>Number : Symbol(Number, Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --)) +>arg : Symbol(arg, Decl(intraExpressionInferences.ts, 302, 8)) + + nested2: { +>nested2 : Symbol(nested2, Decl(intraExpressionInferences.ts, 302, 28)) + + d: (arg) => Boolean(arg), +>d : Symbol(d, Decl(intraExpressionInferences.ts, 303, 14)) +>arg : Symbol(arg, Decl(intraExpressionInferences.ts, 304, 10)) +>Boolean : Symbol(Boolean, Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --)) +>arg : Symbol(arg, Decl(intraExpressionInferences.ts, 304, 10)) + + }, + }, +}); + +declare function distant(args: { +>distant : Symbol(distant, Decl(intraExpressionInferences.ts, 307, 3)) +>T : Symbol(T, Decl(intraExpressionInferences.ts, 309, 25)) +>args : Symbol(args, Decl(intraExpressionInferences.ts, 309, 28)) + + foo: { +>foo : Symbol(foo, Decl(intraExpressionInferences.ts, 309, 35)) + + bar: { +>bar : Symbol(bar, Decl(intraExpressionInferences.ts, 310, 8)) + + baz: { +>baz : Symbol(baz, Decl(intraExpressionInferences.ts, 311, 10)) + + producer: (arg: string) => T; +>producer : Symbol(producer, Decl(intraExpressionInferences.ts, 312, 12)) +>arg : Symbol(arg, Decl(intraExpressionInferences.ts, 313, 19)) +>T : Symbol(T, Decl(intraExpressionInferences.ts, 309, 25)) + + }; + }; + }; + consumer: (val: T) => unknown; +>consumer : Symbol(consumer, Decl(intraExpressionInferences.ts, 316, 4)) +>val : Symbol(val, Decl(intraExpressionInferences.ts, 317, 13)) +>T : Symbol(T, Decl(intraExpressionInferences.ts, 309, 25)) + +}): T; +>T : Symbol(T, Decl(intraExpressionInferences.ts, 309, 25)) + +const distantRes = distant({ +>distantRes : Symbol(distantRes, Decl(intraExpressionInferences.ts, 320, 5)) +>distant : Symbol(distant, Decl(intraExpressionInferences.ts, 307, 3)) + + foo: { +>foo : Symbol(foo, Decl(intraExpressionInferences.ts, 320, 28)) + + bar: { +>bar : Symbol(bar, Decl(intraExpressionInferences.ts, 321, 8)) + + baz: { +>baz : Symbol(baz, Decl(intraExpressionInferences.ts, 322, 10)) + + producer: (arg) => 1, +>producer : Symbol(producer, Decl(intraExpressionInferences.ts, 323, 12)) +>arg : Symbol(arg, Decl(intraExpressionInferences.ts, 324, 19)) + + }, + }, + }, + consumer: (val) => {}, +>consumer : Symbol(consumer, Decl(intraExpressionInferences.ts, 327, 4)) +>val : Symbol(val, Decl(intraExpressionInferences.ts, 328, 13)) + +}); + diff --git a/tests/baselines/reference/intraExpressionInferences.types b/tests/baselines/reference/intraExpressionInferences.types index 3f67a87a25f08..e38c271c8614a 100644 --- a/tests/baselines/reference/intraExpressionInferences.types +++ b/tests/baselines/reference/intraExpressionInferences.types @@ -703,3 +703,417 @@ Foo({ }, }, }); + +declare function nested(arg: { +>nested : (arg: { prop: { produce: (arg1: number) => T; consume: (arg2: T) => void; }; }) => T +>arg : { prop: { produce: (arg1: number) => T; consume: (arg2: T) => void; }; } + + prop: { +>prop : { produce: (arg1: number) => T; consume: (arg2: T) => void; } + + produce: (arg1: number) => T; +>produce : (arg1: number) => T +>arg1 : number + + consume: (arg2: T) => void; +>consume : (arg2: T) => void +>arg2 : T + + }; +}): T; + +const resNested = nested({ +>resNested : number[] +>nested({ prop: { produce: (a) => [a], consume: (arg) => arg.join(","), },}) : number[] +>nested : (arg: { prop: { produce: (arg1: number) => T; consume: (arg2: T) => void; }; }) => T +>{ prop: { produce: (a) => [a], consume: (arg) => arg.join(","), },} : { prop: { produce: (a: number) => number[]; consume: (arg: number[]) => string; }; } + + prop: { +>prop : { produce: (a: number) => number[]; consume: (arg: number[]) => string; } +>{ produce: (a) => [a], consume: (arg) => arg.join(","), } : { produce: (a: number) => number[]; consume: (arg: number[]) => string; } + + produce: (a) => [a], +>produce : (a: number) => number[] +>(a) => [a] : (a: number) => number[] +>a : number +>[a] : number[] +>a : number + + consume: (arg) => arg.join(","), +>consume : (arg: number[]) => string +>(arg) => arg.join(",") : (arg: number[]) => string +>arg : number[] +>arg.join(",") : string +>arg.join : (separator?: string | undefined) => string +>arg : number[] +>join : (separator?: string | undefined) => string +>"," : "," + + }, +}); + +declare function twoConsumers(arg: { +>twoConsumers : (arg: { a: (arg: string) => T; consume1: (arg1: T) => void; consume2: (arg2: T) => void; }) => T +>arg : { a: (arg: string) => T; consume1: (arg1: T) => void; consume2: (arg2: T) => void; } + + a: (arg: string) => T; +>a : (arg: string) => T +>arg : string + + consume1: (arg1: T) => void; +>consume1 : (arg1: T) => void +>arg1 : T + + consume2: (arg2: T) => void; +>consume2 : (arg2: T) => void +>arg2 : T + +}): T; + +const resTwoConsumers = twoConsumers({ +>resTwoConsumers : string[] +>twoConsumers({ a: (arg) => [arg], consume1: (arg1) => {}, consume2: (arg2) => {},}) : string[] +>twoConsumers : (arg: { a: (arg: string) => T; consume1: (arg1: T) => void; consume2: (arg2: T) => void; }) => T +>{ a: (arg) => [arg], consume1: (arg1) => {}, consume2: (arg2) => {},} : { a: (arg: string) => string[]; consume1: (arg1: string[]) => void; consume2: (arg2: string[]) => void; } + + a: (arg) => [arg], +>a : (arg: string) => string[] +>(arg) => [arg] : (arg: string) => string[] +>arg : string +>[arg] : string[] +>arg : string + + consume1: (arg1) => {}, +>consume1 : (arg1: string[]) => void +>(arg1) => {} : (arg1: string[]) => void +>arg1 : string[] + + consume2: (arg2) => {}, +>consume2 : (arg2: string[]) => void +>(arg2) => {} : (arg2: string[]) => void +>arg2 : string[] + +}); + +declare function multipleProducersBeforeConsumers(arg: { +>multipleProducersBeforeConsumers : (arg: { a: (arg: string) => T; b: (arg: string) => T2; consume1: (arg1: T) => void; consume2: (arg2: T2) => void; }) => [T, T2] +>arg : { a: (arg: string) => T; b: (arg: string) => T2; consume1: (arg1: T) => void; consume2: (arg2: T2) => void; } + + a: (arg: string) => T; +>a : (arg: string) => T +>arg : string + + b: (arg: string) => T2; +>b : (arg: string) => T2 +>arg : string + + consume1: (arg1: T) => void; +>consume1 : (arg1: T) => void +>arg1 : T + + consume2: (arg2: T2) => void; +>consume2 : (arg2: T2) => void +>arg2 : T2 + +}): [T, T2]; + +const resMultipleProducersBeforeConsumers = multipleProducersBeforeConsumers({ +>resMultipleProducersBeforeConsumers : [string[], number] +>multipleProducersBeforeConsumers({ a: (arg) => [arg], b: (arg) => Number(arg), consume1: (arg1) => {}, consume2: (arg2) => {},}) : [string[], number] +>multipleProducersBeforeConsumers : (arg: { a: (arg: string) => T; b: (arg: string) => T2; consume1: (arg1: T) => void; consume2: (arg2: T2) => void; }) => [T, T2] +>{ a: (arg) => [arg], b: (arg) => Number(arg), consume1: (arg1) => {}, consume2: (arg2) => {},} : { a: (arg: string) => string[]; b: (arg: string) => number; consume1: (arg1: string[]) => void; consume2: (arg2: number) => void; } + + a: (arg) => [arg], +>a : (arg: string) => string[] +>(arg) => [arg] : (arg: string) => string[] +>arg : string +>[arg] : string[] +>arg : string + + b: (arg) => Number(arg), +>b : (arg: string) => number +>(arg) => Number(arg) : (arg: string) => number +>arg : string +>Number(arg) : number +>Number : NumberConstructor +>arg : string + + consume1: (arg1) => {}, +>consume1 : (arg1: string[]) => void +>(arg1) => {} : (arg1: string[]) => void +>arg1 : string[] + + consume2: (arg2) => {}, +>consume2 : (arg2: number) => void +>(arg2) => {} : (arg2: number) => void +>arg2 : number + +}); + +declare function withConditionalExpression(arg: { +>withConditionalExpression : (arg: { a: (arg1: string) => T; b: (arg2: T) => T2; c: (arg2: T2) => T3; }) => [T, T2, T3] +>arg : { a: (arg1: string) => T; b: (arg2: T) => T2; c: (arg2: T2) => T3; } + + a: (arg1: string) => T; +>a : (arg1: string) => T +>arg1 : string + + b: (arg2: T) => T2; +>b : (arg2: T) => T2 +>arg2 : T + + c: (arg2: T2) => T3; +>c : (arg2: T2) => T3 +>arg2 : T2 + +}): [T, T2, T3]; + +const resWithConditionalExpression = withConditionalExpression({ +>resWithConditionalExpression : [string[], "first" | "two", boolean] +>withConditionalExpression({ a: (arg) => [arg], b: Math.random() ? (arg) => "first" as const : (arg) => "two" as const, c: (arg) => Boolean(arg),}) : [string[], "first" | "two", boolean] +>withConditionalExpression : (arg: { a: (arg1: string) => T; b: (arg2: T) => T2; c: (arg2: T2) => T3; }) => [T, T2, T3] +>{ a: (arg) => [arg], b: Math.random() ? (arg) => "first" as const : (arg) => "two" as const, c: (arg) => Boolean(arg),} : { a: (arg: string) => string[]; b: ((arg: string[]) => "first") | ((arg: string[]) => "two"); c: (arg: "first" | "two") => boolean; } + + a: (arg) => [arg], +>a : (arg: string) => string[] +>(arg) => [arg] : (arg: string) => string[] +>arg : string +>[arg] : string[] +>arg : string + + b: Math.random() ? (arg) => "first" as const : (arg) => "two" as const, +>b : ((arg: string[]) => "first") | ((arg: string[]) => "two") +>Math.random() ? (arg) => "first" as const : (arg) => "two" as const : ((arg: string[]) => "first") | ((arg: string[]) => "two") +>Math.random() : number +>Math.random : () => number +>Math : Math +>random : () => number +>(arg) => "first" as const : (arg: string[]) => "first" +>arg : string[] +>"first" as const : "first" +>"first" : "first" +>(arg) => "two" as const : (arg: string[]) => "two" +>arg : string[] +>"two" as const : "two" +>"two" : "two" + + c: (arg) => Boolean(arg), +>c : (arg: "first" | "two") => boolean +>(arg) => Boolean(arg) : (arg: "first" | "two") => boolean +>arg : "first" | "two" +>Boolean(arg) : boolean +>Boolean : BooleanConstructor +>arg : "first" | "two" + +}); + +declare function onion(arg: { +>onion : (arg: { a: (arg1: string) => T; nested: { b: (arg2: T) => T2; nested2: { c: (arg2: T2) => T3; }; }; }) => [T, T2, T3] +>arg : { a: (arg1: string) => T; nested: { b: (arg2: T) => T2; nested2: { c: (arg2: T2) => T3; }; }; } + + a: (arg1: string) => T; +>a : (arg1: string) => T +>arg1 : string + + nested: { +>nested : { b: (arg2: T) => T2; nested2: { c: (arg2: T2) => T3; }; } + + b: (arg2: T) => T2; +>b : (arg2: T) => T2 +>arg2 : T + + nested2: { +>nested2 : { c: (arg2: T2) => T3; } + + c: (arg2: T2) => T3; +>c : (arg2: T2) => T3 +>arg2 : T2 + + }; + }; +}): [T, T2, T3]; + +const resOnion = onion({ +>resOnion : [string[], string, boolean] +>onion({ a: (arg) => [arg], nested: { b: (arg) => arg.join(","), nested2: { c: (arg) => Boolean(arg), }, },}) : [string[], string, boolean] +>onion : (arg: { a: (arg1: string) => T; nested: { b: (arg2: T) => T2; nested2: { c: (arg2: T2) => T3; }; }; }) => [T, T2, T3] +>{ a: (arg) => [arg], nested: { b: (arg) => arg.join(","), nested2: { c: (arg) => Boolean(arg), }, },} : { a: (arg: string) => string[]; nested: { b: (arg: string[]) => string; nested2: { c: (arg: string) => boolean; }; }; } + + a: (arg) => [arg], +>a : (arg: string) => string[] +>(arg) => [arg] : (arg: string) => string[] +>arg : string +>[arg] : string[] +>arg : string + + nested: { +>nested : { b: (arg: string[]) => string; nested2: { c: (arg: string) => boolean; }; } +>{ b: (arg) => arg.join(","), nested2: { c: (arg) => Boolean(arg), }, } : { b: (arg: string[]) => string; nested2: { c: (arg: string) => boolean; }; } + + b: (arg) => arg.join(","), +>b : (arg: string[]) => string +>(arg) => arg.join(",") : (arg: string[]) => string +>arg : string[] +>arg.join(",") : string +>arg.join : (separator?: string | undefined) => string +>arg : string[] +>join : (separator?: string | undefined) => string +>"," : "," + + nested2: { +>nested2 : { c: (arg: string) => boolean; } +>{ c: (arg) => Boolean(arg), } : { c: (arg: string) => boolean; } + + c: (arg) => Boolean(arg), +>c : (arg: string) => boolean +>(arg) => Boolean(arg) : (arg: string) => boolean +>arg : string +>Boolean(arg) : boolean +>Boolean : BooleanConstructor +>arg : string + + }, + }, +}); + +declare function onion2(arg: { +>onion2 : (arg: { a: (arg1: string) => T; nested: { b: (arg2: T) => T2; c: (arg3: T) => T3; nested2: { d: (arg4: T3) => T4; }; }; }) => [T, T2, T3, T4] +>arg : { a: (arg1: string) => T; nested: { b: (arg2: T) => T2; c: (arg3: T) => T3; nested2: { d: (arg4: T3) => T4; }; }; } + + a: (arg1: string) => T; +>a : (arg1: string) => T +>arg1 : string + + nested: { +>nested : { b: (arg2: T) => T2; c: (arg3: T) => T3; nested2: { d: (arg4: T3) => T4; }; } + + b: (arg2: T) => T2; +>b : (arg2: T) => T2 +>arg2 : T + + c: (arg3: T) => T3; +>c : (arg3: T) => T3 +>arg3 : T + + nested2: { +>nested2 : { d: (arg4: T3) => T4; } + + d: (arg4: T3) => T4; +>d : (arg4: T3) => T4 +>arg4 : T3 + + }; + }; +}): [T, T2, T3, T4]; + +const resOnion2 = onion2({ +>resOnion2 : [string[], string, number, boolean] +>onion2({ a: (arg) => [arg], nested: { b: (arg) => arg.join(","), c: (arg) => Number(arg), nested2: { d: (arg) => Boolean(arg), }, },}) : [string[], string, number, boolean] +>onion2 : (arg: { a: (arg1: string) => T; nested: { b: (arg2: T) => T2; c: (arg3: T) => T3; nested2: { d: (arg4: T3) => T4; }; }; }) => [T, T2, T3, T4] +>{ a: (arg) => [arg], nested: { b: (arg) => arg.join(","), c: (arg) => Number(arg), nested2: { d: (arg) => Boolean(arg), }, },} : { a: (arg: string) => string[]; nested: { b: (arg: string[]) => string; c: (arg: string[]) => number; nested2: { d: (arg: number) => boolean; }; }; } + + a: (arg) => [arg], +>a : (arg: string) => string[] +>(arg) => [arg] : (arg: string) => string[] +>arg : string +>[arg] : string[] +>arg : string + + nested: { +>nested : { b: (arg: string[]) => string; c: (arg: string[]) => number; nested2: { d: (arg: number) => boolean; }; } +>{ b: (arg) => arg.join(","), c: (arg) => Number(arg), nested2: { d: (arg) => Boolean(arg), }, } : { b: (arg: string[]) => string; c: (arg: string[]) => number; nested2: { d: (arg: number) => boolean; }; } + + b: (arg) => arg.join(","), +>b : (arg: string[]) => string +>(arg) => arg.join(",") : (arg: string[]) => string +>arg : string[] +>arg.join(",") : string +>arg.join : (separator?: string | undefined) => string +>arg : string[] +>join : (separator?: string | undefined) => string +>"," : "," + + c: (arg) => Number(arg), +>c : (arg: string[]) => number +>(arg) => Number(arg) : (arg: string[]) => number +>arg : string[] +>Number(arg) : number +>Number : NumberConstructor +>arg : string[] + + nested2: { +>nested2 : { d: (arg: number) => boolean; } +>{ d: (arg) => Boolean(arg), } : { d: (arg: number) => boolean; } + + d: (arg) => Boolean(arg), +>d : (arg: number) => boolean +>(arg) => Boolean(arg) : (arg: number) => boolean +>arg : number +>Boolean(arg) : boolean +>Boolean : BooleanConstructor +>arg : number + + }, + }, +}); + +declare function distant(args: { +>distant : (args: { foo: { bar: { baz: { producer: (arg: string) => T; }; }; }; consumer: (val: T) => unknown; }) => T +>args : { foo: { bar: { baz: { producer: (arg: string) => T; }; }; }; consumer: (val: T) => unknown; } + + foo: { +>foo : { bar: { baz: { producer: (arg: string) => T; }; }; } + + bar: { +>bar : { baz: { producer: (arg: string) => T; }; } + + baz: { +>baz : { producer: (arg: string) => T; } + + producer: (arg: string) => T; +>producer : (arg: string) => T +>arg : string + + }; + }; + }; + consumer: (val: T) => unknown; +>consumer : (val: T) => unknown +>val : T + +}): T; + +const distantRes = distant({ +>distantRes : number +>distant({ foo: { bar: { baz: { producer: (arg) => 1, }, }, }, consumer: (val) => {},}) : number +>distant : (args: { foo: { bar: { baz: { producer: (arg: string) => T; }; }; }; consumer: (val: T) => unknown; }) => T +>{ foo: { bar: { baz: { producer: (arg) => 1, }, }, }, consumer: (val) => {},} : { foo: { bar: { baz: { producer: (arg: string) => number; }; }; }; consumer: (val: number) => void; } + + foo: { +>foo : { bar: { baz: { producer: (arg: string) => number; }; }; } +>{ bar: { baz: { producer: (arg) => 1, }, }, } : { bar: { baz: { producer: (arg: string) => number; }; }; } + + bar: { +>bar : { baz: { producer: (arg: string) => number; }; } +>{ baz: { producer: (arg) => 1, }, } : { baz: { producer: (arg: string) => number; }; } + + baz: { +>baz : { producer: (arg: string) => number; } +>{ producer: (arg) => 1, } : { producer: (arg: string) => number; } + + producer: (arg) => 1, +>producer : (arg: string) => number +>(arg) => 1 : (arg: string) => number +>arg : string +>1 : 1 + + }, + }, + }, + consumer: (val) => {}, +>consumer : (val: number) => void +>(val) => {} : (val: number) => void +>val : number + +}); + diff --git a/tests/cases/conformance/types/typeRelationships/typeInference/intraExpressionInferences.ts b/tests/cases/conformance/types/typeRelationships/typeInference/intraExpressionInferences.ts index 9fdbebfa028b1..6d23f571d41f3 100644 --- a/tests/cases/conformance/types/typeRelationships/typeInference/intraExpressionInferences.ts +++ b/tests/cases/conformance/types/typeRelationships/typeInference/intraExpressionInferences.ts @@ -214,4 +214,120 @@ Foo({ arg.toString(); }, }, -}); \ No newline at end of file +}); + +declare function nested(arg: { + prop: { + produce: (arg1: number) => T; + consume: (arg2: T) => void; + }; +}): T; + +const resNested = nested({ + prop: { + produce: (a) => [a], + consume: (arg) => arg.join(","), + }, +}); + +declare function twoConsumers(arg: { + a: (arg: string) => T; + consume1: (arg1: T) => void; + consume2: (arg2: T) => void; +}): T; + +const resTwoConsumers = twoConsumers({ + a: (arg) => [arg], + consume1: (arg1) => {}, + consume2: (arg2) => {}, +}); + +declare function multipleProducersBeforeConsumers(arg: { + a: (arg: string) => T; + b: (arg: string) => T2; + consume1: (arg1: T) => void; + consume2: (arg2: T2) => void; +}): [T, T2]; + +const resMultipleProducersBeforeConsumers = multipleProducersBeforeConsumers({ + a: (arg) => [arg], + b: (arg) => Number(arg), + consume1: (arg1) => {}, + consume2: (arg2) => {}, +}); + +declare function withConditionalExpression(arg: { + a: (arg1: string) => T; + b: (arg2: T) => T2; + c: (arg2: T2) => T3; +}): [T, T2, T3]; + +const resWithConditionalExpression = withConditionalExpression({ + a: (arg) => [arg], + b: Math.random() ? (arg) => "first" as const : (arg) => "two" as const, + c: (arg) => Boolean(arg), +}); + +declare function onion(arg: { + a: (arg1: string) => T; + nested: { + b: (arg2: T) => T2; + nested2: { + c: (arg2: T2) => T3; + }; + }; +}): [T, T2, T3]; + +const resOnion = onion({ + a: (arg) => [arg], + nested: { + b: (arg) => arg.join(","), + nested2: { + c: (arg) => Boolean(arg), + }, + }, +}); + +declare function onion2(arg: { + a: (arg1: string) => T; + nested: { + b: (arg2: T) => T2; + c: (arg3: T) => T3; + nested2: { + d: (arg4: T3) => T4; + }; + }; +}): [T, T2, T3, T4]; + +const resOnion2 = onion2({ + a: (arg) => [arg], + nested: { + b: (arg) => arg.join(","), + c: (arg) => Number(arg), + nested2: { + d: (arg) => Boolean(arg), + }, + }, +}); + +declare function distant(args: { + foo: { + bar: { + baz: { + producer: (arg: string) => T; + }; + }; + }; + consumer: (val: T) => unknown; +}): T; + +const distantRes = distant({ + foo: { + bar: { + baz: { + producer: (arg) => 1, + }, + }, + }, + consumer: (val) => {}, +});