From 65b54ad99801d0c073297e6863228f82a5336744 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mateusz=20Burzy=C5=84ski?= Date: Sat, 3 Aug 2024 10:43:00 +0200 Subject: [PATCH 1/8] Infer from context sensitive return expressions --- src/compiler/checker.ts | 22 +- ...ExpressionInferencesInContextSensitive1.js | 145 ++++++++ ...ssionInferencesInContextSensitive1.symbols | 218 +++++++++++ ...ressionInferencesInContextSensitive1.types | 350 ++++++++++++++++++ ...ExpressionInferencesInContextSensitive1.ts | 76 ++++ 5 files changed, 807 insertions(+), 4 deletions(-) create mode 100644 tests/baselines/reference/intraExpressionInferencesInContextSensitive1.js create mode 100644 tests/baselines/reference/intraExpressionInferencesInContextSensitive1.symbols create mode 100644 tests/baselines/reference/intraExpressionInferencesInContextSensitive1.types create mode 100644 tests/cases/conformance/types/typeRelationships/typeInference/intraExpressionInferencesInContextSensitive1.ts diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 80b61edd3657a..5ba037cb5064a 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -38938,7 +38938,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { return getTypeOfSymbol(getSymbolOfDeclaration(node)); } - function contextuallyCheckFunctionExpressionOrObjectLiteralMethod(node: FunctionExpression | ArrowFunction | MethodDeclaration, checkMode?: CheckMode) { + function contextuallyCheckFunctionExpressionOrObjectLiteralMethod(node: FunctionExpression | ArrowFunction | MethodDeclaration, checkMode = CheckMode.Normal) { const links = getNodeLinks(node); // Check if function expression is contextually typed and assign parameter types if so. if (!(links.flags & NodeCheckFlags.ContextChecked)) { @@ -38956,7 +38956,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { if (contextualSignature) { const inferenceContext = getInferenceContext(node); let instantiatedContextualSignature: Signature | undefined; - if (checkMode && checkMode & CheckMode.Inferential) { + if (checkMode & CheckMode.Inferential) { inferFromAnnotatedParameters(signature, contextualSignature, inferenceContext!); const restType = getEffectiveRestType(contextualSignature); if (restType && restType.flags & TypeFlags.TypeParameter) { @@ -38974,12 +38974,26 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { } else if (contextualSignature && !node.typeParameters && contextualSignature.parameters.length > node.parameters.length) { const inferenceContext = getInferenceContext(node); - if (checkMode && checkMode & CheckMode.Inferential) { + if (checkMode & CheckMode.Inferential) { inferFromAnnotatedParameters(signature, contextualSignature, inferenceContext!); } } if (contextualSignature && !getReturnTypeFromAnnotation(node) && !signature.resolvedReturnType) { - const returnType = getReturnTypeFromBody(node, checkMode); + let contextualReturnType: Type; + let returnType: Type; + + if (checkMode & CheckMode.Inferential && couldContainTypeVariables(contextualReturnType = getReturnTypeOfSignature(contextualSignature))) { + const inferenceContext = getInferenceContext(node); + const isReturnContextSensitive = !!node.body && (node.body.kind === SyntaxKind.Block ? forEachReturnStatement(node.body as Block, statement => !!statement.expression && isContextSensitive(statement.expression)) : isContextSensitive(node.body)); + returnType = getReturnTypeFromBody(node, checkMode | (isReturnContextSensitive ? CheckMode.SkipContextSensitive : 0)); + inferTypes(inferenceContext!.inferences, returnType, contextualReturnType); + if (isReturnContextSensitive) { + returnType = getReturnTypeFromBody(node, checkMode); + } + } else { + returnType = getReturnTypeFromBody(node, checkMode); + } + if (!signature.resolvedReturnType) { signature.resolvedReturnType = returnType; } diff --git a/tests/baselines/reference/intraExpressionInferencesInContextSensitive1.js b/tests/baselines/reference/intraExpressionInferencesInContextSensitive1.js new file mode 100644 index 0000000000000..1ac170d9174bc --- /dev/null +++ b/tests/baselines/reference/intraExpressionInferencesInContextSensitive1.js @@ -0,0 +1,145 @@ +//// [tests/cases/conformance/types/typeRelationships/typeInference/intraExpressionInferencesInContextSensitive1.ts] //// + +//// [intraExpressionInferencesInContextSensitive1.ts] +// https://github.com/microsoft/TypeScript/issues/60720 + +type Options = { + onStart?: () => TContext; + onEnd?: (context: TContext) => void; +}; + +function create(builder: (arg: boolean) => Options) { + return builder(true); +} + +create((arg: boolean) => ({ + onStart: () => ({ time: new Date() }), + onEnd: (context) => {}, +})); + +create(() => ({ + onStart: () => ({ time: new Date() }), + onEnd: (context) => {}, +})); + +create((arg) => ({ + onStart: () => ({ time: new Date() }), + onEnd: (context) => {}, +})); + +// https://github.com/microsoft/TypeScript/issues/57021 + +type Schema = Record; + +type StepFunction = (anything: unknown) => { + readonly schema: TSchema; + readonly toAnswers?: (keys: keyof TSchema) => unknown; +}; + +function step1( + stepVal: StepFunction, +): StepFunction { + return stepVal; +} + +const stepResult1 = step1((_something) => ({ + schema: { + attribute: "anything", + }, + toAnswers: (keys) => { + type Test = string extends typeof keys ? never : "true"; + const test: Test = "true"; // ok + return { test }; + }, +})); + +type StepFunction2 = (anything: unknown) => { + readonly schema: (thing: number) => TSchema; + readonly toAnswers?: (keys: keyof TSchema) => unknown; +}; + +function step2( + stepVal: StepFunction2, +): StepFunction2 { + return stepVal; +} + +const stepResult2 = step2((_something) => ({ + schema: (thing) => ({ + attribute: "anything", + }), + toAnswers: (keys) => { + type Test = string extends typeof keys ? never : "true"; + const test: Test = "true"; // ok + return { test }; + }, +})); + + +//// [intraExpressionInferencesInContextSensitive1.js] +"use strict"; +// https://github.com/microsoft/TypeScript/issues/60720 +function create(builder) { + return builder(true); +} +create(function (arg) { return ({ + onStart: function () { return ({ time: new Date() }); }, + onEnd: function (context) { }, +}); }); +create(function () { return ({ + onStart: function () { return ({ time: new Date() }); }, + onEnd: function (context) { }, +}); }); +create(function (arg) { return ({ + onStart: function () { return ({ time: new Date() }); }, + onEnd: function (context) { }, +}); }); +function step1(stepVal) { + return stepVal; +} +var stepResult1 = step1(function (_something) { return ({ + schema: { + attribute: "anything", + }, + toAnswers: function (keys) { + var test = "true"; // ok + return { test: test }; + }, +}); }); +function step2(stepVal) { + return stepVal; +} +var stepResult2 = step2(function (_something) { return ({ + schema: function (thing) { return ({ + attribute: "anything", + }); }, + toAnswers: function (keys) { + var test = "true"; // ok + return { test: test }; + }, +}); }); + + +//// [intraExpressionInferencesInContextSensitive1.d.ts] +type Options = { + onStart?: () => TContext; + onEnd?: (context: TContext) => void; +}; +declare function create(builder: (arg: boolean) => Options): Options; +type Schema = Record; +type StepFunction = (anything: unknown) => { + readonly schema: TSchema; + readonly toAnswers?: (keys: keyof TSchema) => unknown; +}; +declare function step1(stepVal: StepFunction): StepFunction; +declare const stepResult1: StepFunction<{ + attribute: string; +}>; +type StepFunction2 = (anything: unknown) => { + readonly schema: (thing: number) => TSchema; + readonly toAnswers?: (keys: keyof TSchema) => unknown; +}; +declare function step2(stepVal: StepFunction2): StepFunction2; +declare const stepResult2: StepFunction2<{ + attribute: string; +}>; diff --git a/tests/baselines/reference/intraExpressionInferencesInContextSensitive1.symbols b/tests/baselines/reference/intraExpressionInferencesInContextSensitive1.symbols new file mode 100644 index 0000000000000..db64f13f17225 --- /dev/null +++ b/tests/baselines/reference/intraExpressionInferencesInContextSensitive1.symbols @@ -0,0 +1,218 @@ +//// [tests/cases/conformance/types/typeRelationships/typeInference/intraExpressionInferencesInContextSensitive1.ts] //// + +=== intraExpressionInferencesInContextSensitive1.ts === +// https://github.com/microsoft/TypeScript/issues/60720 + +type Options = { +>Options : Symbol(Options, Decl(intraExpressionInferencesInContextSensitive1.ts, 0, 0)) +>TContext : Symbol(TContext, Decl(intraExpressionInferencesInContextSensitive1.ts, 2, 13)) + + onStart?: () => TContext; +>onStart : Symbol(onStart, Decl(intraExpressionInferencesInContextSensitive1.ts, 2, 26)) +>TContext : Symbol(TContext, Decl(intraExpressionInferencesInContextSensitive1.ts, 2, 13)) + + onEnd?: (context: TContext) => void; +>onEnd : Symbol(onEnd, Decl(intraExpressionInferencesInContextSensitive1.ts, 3, 27)) +>context : Symbol(context, Decl(intraExpressionInferencesInContextSensitive1.ts, 4, 11)) +>TContext : Symbol(TContext, Decl(intraExpressionInferencesInContextSensitive1.ts, 2, 13)) + +}; + +function create(builder: (arg: boolean) => Options) { +>create : Symbol(create, Decl(intraExpressionInferencesInContextSensitive1.ts, 5, 2)) +>TContext : Symbol(TContext, Decl(intraExpressionInferencesInContextSensitive1.ts, 7, 16)) +>builder : Symbol(builder, Decl(intraExpressionInferencesInContextSensitive1.ts, 7, 26)) +>arg : Symbol(arg, Decl(intraExpressionInferencesInContextSensitive1.ts, 7, 36)) +>Options : Symbol(Options, Decl(intraExpressionInferencesInContextSensitive1.ts, 0, 0)) +>TContext : Symbol(TContext, Decl(intraExpressionInferencesInContextSensitive1.ts, 7, 16)) + + return builder(true); +>builder : Symbol(builder, Decl(intraExpressionInferencesInContextSensitive1.ts, 7, 26)) +} + +create((arg: boolean) => ({ +>create : Symbol(create, Decl(intraExpressionInferencesInContextSensitive1.ts, 5, 2)) +>arg : Symbol(arg, Decl(intraExpressionInferencesInContextSensitive1.ts, 11, 8)) + + onStart: () => ({ time: new Date() }), +>onStart : Symbol(onStart, Decl(intraExpressionInferencesInContextSensitive1.ts, 11, 27)) +>time : Symbol(time, Decl(intraExpressionInferencesInContextSensitive1.ts, 12, 19)) +>Date : Symbol(Date, Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --), Decl(lib.scripthost.d.ts, --, --)) + + onEnd: (context) => {}, +>onEnd : Symbol(onEnd, Decl(intraExpressionInferencesInContextSensitive1.ts, 12, 40)) +>context : Symbol(context, Decl(intraExpressionInferencesInContextSensitive1.ts, 13, 10)) + +})); + +create(() => ({ +>create : Symbol(create, Decl(intraExpressionInferencesInContextSensitive1.ts, 5, 2)) + + onStart: () => ({ time: new Date() }), +>onStart : Symbol(onStart, Decl(intraExpressionInferencesInContextSensitive1.ts, 16, 15)) +>time : Symbol(time, Decl(intraExpressionInferencesInContextSensitive1.ts, 17, 19)) +>Date : Symbol(Date, Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --), Decl(lib.scripthost.d.ts, --, --)) + + onEnd: (context) => {}, +>onEnd : Symbol(onEnd, Decl(intraExpressionInferencesInContextSensitive1.ts, 17, 40)) +>context : Symbol(context, Decl(intraExpressionInferencesInContextSensitive1.ts, 18, 10)) + +})); + +create((arg) => ({ +>create : Symbol(create, Decl(intraExpressionInferencesInContextSensitive1.ts, 5, 2)) +>arg : Symbol(arg, Decl(intraExpressionInferencesInContextSensitive1.ts, 21, 8)) + + onStart: () => ({ time: new Date() }), +>onStart : Symbol(onStart, Decl(intraExpressionInferencesInContextSensitive1.ts, 21, 18)) +>time : Symbol(time, Decl(intraExpressionInferencesInContextSensitive1.ts, 22, 19)) +>Date : Symbol(Date, Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --), Decl(lib.scripthost.d.ts, --, --)) + + onEnd: (context) => {}, +>onEnd : Symbol(onEnd, Decl(intraExpressionInferencesInContextSensitive1.ts, 22, 40)) +>context : Symbol(context, Decl(intraExpressionInferencesInContextSensitive1.ts, 23, 10)) + +})); + +// https://github.com/microsoft/TypeScript/issues/57021 + +type Schema = Record; +>Schema : Symbol(Schema, Decl(intraExpressionInferencesInContextSensitive1.ts, 24, 4)) +>Record : Symbol(Record, Decl(lib.es5.d.ts, --, --)) + +type StepFunction = (anything: unknown) => { +>StepFunction : Symbol(StepFunction, Decl(intraExpressionInferencesInContextSensitive1.ts, 28, 38)) +>TSchema : Symbol(TSchema, Decl(intraExpressionInferencesInContextSensitive1.ts, 30, 18)) +>Schema : Symbol(Schema, Decl(intraExpressionInferencesInContextSensitive1.ts, 24, 4)) +>Schema : Symbol(Schema, Decl(intraExpressionInferencesInContextSensitive1.ts, 24, 4)) +>anything : Symbol(anything, Decl(intraExpressionInferencesInContextSensitive1.ts, 30, 54)) + + readonly schema: TSchema; +>schema : Symbol(schema, Decl(intraExpressionInferencesInContextSensitive1.ts, 30, 77)) +>TSchema : Symbol(TSchema, Decl(intraExpressionInferencesInContextSensitive1.ts, 30, 18)) + + readonly toAnswers?: (keys: keyof TSchema) => unknown; +>toAnswers : Symbol(toAnswers, Decl(intraExpressionInferencesInContextSensitive1.ts, 31, 27)) +>keys : Symbol(keys, Decl(intraExpressionInferencesInContextSensitive1.ts, 32, 24)) +>TSchema : Symbol(TSchema, Decl(intraExpressionInferencesInContextSensitive1.ts, 30, 18)) + +}; + +function step1( +>step1 : Symbol(step1, Decl(intraExpressionInferencesInContextSensitive1.ts, 33, 2)) +>TSchema : Symbol(TSchema, Decl(intraExpressionInferencesInContextSensitive1.ts, 35, 15)) +>Schema : Symbol(Schema, Decl(intraExpressionInferencesInContextSensitive1.ts, 24, 4)) +>Schema : Symbol(Schema, Decl(intraExpressionInferencesInContextSensitive1.ts, 24, 4)) + + stepVal: StepFunction, +>stepVal : Symbol(stepVal, Decl(intraExpressionInferencesInContextSensitive1.ts, 35, 48)) +>StepFunction : Symbol(StepFunction, Decl(intraExpressionInferencesInContextSensitive1.ts, 28, 38)) +>TSchema : Symbol(TSchema, Decl(intraExpressionInferencesInContextSensitive1.ts, 35, 15)) + +): StepFunction { +>StepFunction : Symbol(StepFunction, Decl(intraExpressionInferencesInContextSensitive1.ts, 28, 38)) +>TSchema : Symbol(TSchema, Decl(intraExpressionInferencesInContextSensitive1.ts, 35, 15)) + + return stepVal; +>stepVal : Symbol(stepVal, Decl(intraExpressionInferencesInContextSensitive1.ts, 35, 48)) +} + +const stepResult1 = step1((_something) => ({ +>stepResult1 : Symbol(stepResult1, Decl(intraExpressionInferencesInContextSensitive1.ts, 41, 5)) +>step1 : Symbol(step1, Decl(intraExpressionInferencesInContextSensitive1.ts, 33, 2)) +>_something : Symbol(_something, Decl(intraExpressionInferencesInContextSensitive1.ts, 41, 27)) + + schema: { +>schema : Symbol(schema, Decl(intraExpressionInferencesInContextSensitive1.ts, 41, 44)) + + attribute: "anything", +>attribute : Symbol(attribute, Decl(intraExpressionInferencesInContextSensitive1.ts, 42, 11)) + + }, + toAnswers: (keys) => { +>toAnswers : Symbol(toAnswers, Decl(intraExpressionInferencesInContextSensitive1.ts, 44, 4)) +>keys : Symbol(keys, Decl(intraExpressionInferencesInContextSensitive1.ts, 45, 14)) + + type Test = string extends typeof keys ? never : "true"; +>Test : Symbol(Test, Decl(intraExpressionInferencesInContextSensitive1.ts, 45, 24)) +>keys : Symbol(keys, Decl(intraExpressionInferencesInContextSensitive1.ts, 45, 14)) + + const test: Test = "true"; // ok +>test : Symbol(test, Decl(intraExpressionInferencesInContextSensitive1.ts, 47, 9)) +>Test : Symbol(Test, Decl(intraExpressionInferencesInContextSensitive1.ts, 45, 24)) + + return { test }; +>test : Symbol(test, Decl(intraExpressionInferencesInContextSensitive1.ts, 48, 12)) + + }, +})); + +type StepFunction2 = (anything: unknown) => { +>StepFunction2 : Symbol(StepFunction2, Decl(intraExpressionInferencesInContextSensitive1.ts, 50, 4)) +>TSchema : Symbol(TSchema, Decl(intraExpressionInferencesInContextSensitive1.ts, 52, 19)) +>Schema : Symbol(Schema, Decl(intraExpressionInferencesInContextSensitive1.ts, 24, 4)) +>Schema : Symbol(Schema, Decl(intraExpressionInferencesInContextSensitive1.ts, 24, 4)) +>anything : Symbol(anything, Decl(intraExpressionInferencesInContextSensitive1.ts, 52, 55)) + + readonly schema: (thing: number) => TSchema; +>schema : Symbol(schema, Decl(intraExpressionInferencesInContextSensitive1.ts, 52, 78)) +>thing : Symbol(thing, Decl(intraExpressionInferencesInContextSensitive1.ts, 53, 20)) +>TSchema : Symbol(TSchema, Decl(intraExpressionInferencesInContextSensitive1.ts, 52, 19)) + + readonly toAnswers?: (keys: keyof TSchema) => unknown; +>toAnswers : Symbol(toAnswers, Decl(intraExpressionInferencesInContextSensitive1.ts, 53, 46)) +>keys : Symbol(keys, Decl(intraExpressionInferencesInContextSensitive1.ts, 54, 24)) +>TSchema : Symbol(TSchema, Decl(intraExpressionInferencesInContextSensitive1.ts, 52, 19)) + +}; + +function step2( +>step2 : Symbol(step2, Decl(intraExpressionInferencesInContextSensitive1.ts, 55, 2)) +>TSchema : Symbol(TSchema, Decl(intraExpressionInferencesInContextSensitive1.ts, 57, 15)) +>Schema : Symbol(Schema, Decl(intraExpressionInferencesInContextSensitive1.ts, 24, 4)) +>Schema : Symbol(Schema, Decl(intraExpressionInferencesInContextSensitive1.ts, 24, 4)) + + stepVal: StepFunction2, +>stepVal : Symbol(stepVal, Decl(intraExpressionInferencesInContextSensitive1.ts, 57, 48)) +>StepFunction2 : Symbol(StepFunction2, Decl(intraExpressionInferencesInContextSensitive1.ts, 50, 4)) +>TSchema : Symbol(TSchema, Decl(intraExpressionInferencesInContextSensitive1.ts, 57, 15)) + +): StepFunction2 { +>StepFunction2 : Symbol(StepFunction2, Decl(intraExpressionInferencesInContextSensitive1.ts, 50, 4)) +>TSchema : Symbol(TSchema, Decl(intraExpressionInferencesInContextSensitive1.ts, 57, 15)) + + return stepVal; +>stepVal : Symbol(stepVal, Decl(intraExpressionInferencesInContextSensitive1.ts, 57, 48)) +} + +const stepResult2 = step2((_something) => ({ +>stepResult2 : Symbol(stepResult2, Decl(intraExpressionInferencesInContextSensitive1.ts, 63, 5)) +>step2 : Symbol(step2, Decl(intraExpressionInferencesInContextSensitive1.ts, 55, 2)) +>_something : Symbol(_something, Decl(intraExpressionInferencesInContextSensitive1.ts, 63, 27)) + + schema: (thing) => ({ +>schema : Symbol(schema, Decl(intraExpressionInferencesInContextSensitive1.ts, 63, 44)) +>thing : Symbol(thing, Decl(intraExpressionInferencesInContextSensitive1.ts, 64, 11)) + + attribute: "anything", +>attribute : Symbol(attribute, Decl(intraExpressionInferencesInContextSensitive1.ts, 64, 23)) + + }), + toAnswers: (keys) => { +>toAnswers : Symbol(toAnswers, Decl(intraExpressionInferencesInContextSensitive1.ts, 66, 5)) +>keys : Symbol(keys, Decl(intraExpressionInferencesInContextSensitive1.ts, 67, 14)) + + type Test = string extends typeof keys ? never : "true"; +>Test : Symbol(Test, Decl(intraExpressionInferencesInContextSensitive1.ts, 67, 24)) +>keys : Symbol(keys, Decl(intraExpressionInferencesInContextSensitive1.ts, 67, 14)) + + const test: Test = "true"; // ok +>test : Symbol(test, Decl(intraExpressionInferencesInContextSensitive1.ts, 69, 9)) +>Test : Symbol(Test, Decl(intraExpressionInferencesInContextSensitive1.ts, 67, 24)) + + return { test }; +>test : Symbol(test, Decl(intraExpressionInferencesInContextSensitive1.ts, 70, 12)) + + }, +})); + diff --git a/tests/baselines/reference/intraExpressionInferencesInContextSensitive1.types b/tests/baselines/reference/intraExpressionInferencesInContextSensitive1.types new file mode 100644 index 0000000000000..deae7c6324933 --- /dev/null +++ b/tests/baselines/reference/intraExpressionInferencesInContextSensitive1.types @@ -0,0 +1,350 @@ +//// [tests/cases/conformance/types/typeRelationships/typeInference/intraExpressionInferencesInContextSensitive1.ts] //// + +=== intraExpressionInferencesInContextSensitive1.ts === +// https://github.com/microsoft/TypeScript/issues/60720 + +type Options = { +>Options : Options +> : ^^^^^^^^^^^^^^^^^ + + onStart?: () => TContext; +>onStart : (() => TContext) | undefined +> : ^^^^^^^ ^^^^^^^^^^^^^ + + onEnd?: (context: TContext) => void; +>onEnd : ((context: TContext) => void) | undefined +> : ^^ ^^ ^^^^^ ^^^^^^^^^^^^^ +>context : TContext +> : ^^^^^^^^ + +}; + +function create(builder: (arg: boolean) => Options) { +>create : (builder: (arg: boolean) => Options) => Options +> : ^ ^^ ^^ ^^^^^^^^^^^^^^^^^^^^^^ +>builder : (arg: boolean) => Options +> : ^ ^^ ^^^^^ +>arg : boolean +> : ^^^^^^^ + + return builder(true); +>builder(true) : Options +> : ^^^^^^^^^^^^^^^^^ +>builder : (arg: boolean) => Options +> : ^ ^^ ^^^^^ +>true : true +> : ^^^^ +} + +create((arg: boolean) => ({ +>create((arg: boolean) => ({ onStart: () => ({ time: new Date() }), onEnd: (context) => {},})) : Options<{ time: Date; }> +> : ^^^^^^^^^^^^^^^^^^^^^^^^ +>create : (builder: (arg: boolean) => Options) => Options +> : ^ ^^ ^^ ^^^^^^^^^^^^^^^^^^^^^^ +>(arg: boolean) => ({ onStart: () => ({ time: new Date() }), onEnd: (context) => {},}) : (arg: boolean) => { onStart: () => { time: Date; }; onEnd: (context: { time: Date; }) => void; } +> : ^ ^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +>arg : boolean +> : ^^^^^^^ +>({ onStart: () => ({ time: new Date() }), onEnd: (context) => {},}) : { onStart: () => { time: Date; }; onEnd: (context: { time: Date; }) => void; } +> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +>{ onStart: () => ({ time: new Date() }), onEnd: (context) => {},} : { onStart: () => { time: Date; }; onEnd: (context: { time: Date; }) => void; } +> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + + onStart: () => ({ time: new Date() }), +>onStart : () => { time: Date; } +> : ^^^^^^^^^^^^^^^^^^^^^ +>() => ({ time: new Date() }) : () => { time: Date; } +> : ^^^^^^^^^^^^^^^^^^^^^ +>({ time: new Date() }) : { time: Date; } +> : ^^^^^^^^^^^^^^^ +>{ time: new Date() } : { time: Date; } +> : ^^^^^^^^^^^^^^^ +>time : Date +> : ^^^^ +>new Date() : Date +> : ^^^^ +>Date : DateConstructor +> : ^^^^^^^^^^^^^^^ + + onEnd: (context) => {}, +>onEnd : (context: { time: Date; }) => void +> : ^ ^^^^^^^^^^^^^^^^^^^^^^^^^^ +>(context) => {} : (context: { time: Date; }) => void +> : ^ ^^^^^^^^^^^^^^^^^^^^^^^^^^ +>context : { time: Date; } +> : ^^^^^^^^^^^^^^^ + +})); + +create(() => ({ +>create(() => ({ onStart: () => ({ time: new Date() }), onEnd: (context) => {},})) : Options<{ time: Date; }> +> : ^^^^^^^^^^^^^^^^^^^^^^^^ +>create : (builder: (arg: boolean) => Options) => Options +> : ^ ^^ ^^ ^^^^^^^^^^^^^^^^^^^^^^ +>() => ({ onStart: () => ({ time: new Date() }), onEnd: (context) => {},}) : () => { onStart: () => { time: Date; }; onEnd: (context: { time: Date; }) => void; } +> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +>({ onStart: () => ({ time: new Date() }), onEnd: (context) => {},}) : { onStart: () => { time: Date; }; onEnd: (context: { time: Date; }) => void; } +> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +>{ onStart: () => ({ time: new Date() }), onEnd: (context) => {},} : { onStart: () => { time: Date; }; onEnd: (context: { time: Date; }) => void; } +> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + + onStart: () => ({ time: new Date() }), +>onStart : () => { time: Date; } +> : ^^^^^^^^^^^^^^^^^^^^^ +>() => ({ time: new Date() }) : () => { time: Date; } +> : ^^^^^^^^^^^^^^^^^^^^^ +>({ time: new Date() }) : { time: Date; } +> : ^^^^^^^^^^^^^^^ +>{ time: new Date() } : { time: Date; } +> : ^^^^^^^^^^^^^^^ +>time : Date +> : ^^^^ +>new Date() : Date +> : ^^^^ +>Date : DateConstructor +> : ^^^^^^^^^^^^^^^ + + onEnd: (context) => {}, +>onEnd : (context: { time: Date; }) => void +> : ^ ^^^^^^^^^^^^^^^^^^^^^^^^^^ +>(context) => {} : (context: { time: Date; }) => void +> : ^ ^^^^^^^^^^^^^^^^^^^^^^^^^^ +>context : { time: Date; } +> : ^^^^^^^^^^^^^^^ + +})); + +create((arg) => ({ +>create((arg) => ({ onStart: () => ({ time: new Date() }), onEnd: (context) => {},})) : Options<{ time: Date; }> +> : ^^^^^^^^^^^^^^^^^^^^^^^^ +>create : (builder: (arg: boolean) => Options) => Options +> : ^ ^^ ^^ ^^^^^^^^^^^^^^^^^^^^^^ +>(arg) => ({ onStart: () => ({ time: new Date() }), onEnd: (context) => {},}) : (arg: boolean) => { onStart: () => { time: Date; }; onEnd: (context: { time: Date; }) => void; } +> : ^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +>arg : boolean +> : ^^^^^^^ +>({ onStart: () => ({ time: new Date() }), onEnd: (context) => {},}) : { onStart: () => { time: Date; }; onEnd: (context: { time: Date; }) => void; } +> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +>{ onStart: () => ({ time: new Date() }), onEnd: (context) => {},} : { onStart: () => { time: Date; }; onEnd: (context: { time: Date; }) => void; } +> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + + onStart: () => ({ time: new Date() }), +>onStart : () => { time: Date; } +> : ^^^^^^^^^^^^^^^^^^^^^ +>() => ({ time: new Date() }) : () => { time: Date; } +> : ^^^^^^^^^^^^^^^^^^^^^ +>({ time: new Date() }) : { time: Date; } +> : ^^^^^^^^^^^^^^^ +>{ time: new Date() } : { time: Date; } +> : ^^^^^^^^^^^^^^^ +>time : Date +> : ^^^^ +>new Date() : Date +> : ^^^^ +>Date : DateConstructor +> : ^^^^^^^^^^^^^^^ + + onEnd: (context) => {}, +>onEnd : (context: { time: Date; }) => void +> : ^ ^^^^^^^^^^^^^^^^^^^^^^^^^^ +>(context) => {} : (context: { time: Date; }) => void +> : ^ ^^^^^^^^^^^^^^^^^^^^^^^^^^ +>context : { time: Date; } +> : ^^^^^^^^^^^^^^^ + +})); + +// https://github.com/microsoft/TypeScript/issues/57021 + +type Schema = Record; +>Schema : Schema +> : ^^^^^^ + +type StepFunction = (anything: unknown) => { +>StepFunction : StepFunction +> : ^^^^^^^^^^^^^^^^^^^^^ +>anything : unknown +> : ^^^^^^^ + + readonly schema: TSchema; +>schema : TSchema +> : ^^^^^^^ + + readonly toAnswers?: (keys: keyof TSchema) => unknown; +>toAnswers : ((keys: keyof TSchema) => unknown) | undefined +> : ^^ ^^ ^^^^^ ^^^^^^^^^^^^^ +>keys : keyof TSchema +> : ^^^^^^^^^^^^^ + +}; + +function step1( +>step1 : (stepVal: StepFunction) => StepFunction +> : ^ ^^^^^^^^^ ^^^^^^^^^^^ ^^ ^^^^^ + + stepVal: StepFunction, +>stepVal : StepFunction +> : ^^^^^^^^^^^^^^^^^^^^^ + +): StepFunction { + return stepVal; +>stepVal : StepFunction +> : ^^^^^^^^^^^^^^^^^^^^^ +} + +const stepResult1 = step1((_something) => ({ +>stepResult1 : StepFunction<{ attribute: string; }> +> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +>step1((_something) => ({ schema: { attribute: "anything", }, toAnswers: (keys) => { type Test = string extends typeof keys ? never : "true"; const test: Test = "true"; // ok return { test }; },})) : StepFunction<{ attribute: string; }> +> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +>step1 : (stepVal: StepFunction) => StepFunction +> : ^ ^^^^^^^^^ ^^^^^^^^^^^ ^^ ^^^^^ +>(_something) => ({ schema: { attribute: "anything", }, toAnswers: (keys) => { type Test = string extends typeof keys ? never : "true"; const test: Test = "true"; // ok return { test }; },}) : (_something: unknown) => { schema: { attribute: string; }; toAnswers: (keys: "attribute") => { test: "true"; }; } +> : ^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +>_something : unknown +> : ^^^^^^^ +>({ schema: { attribute: "anything", }, toAnswers: (keys) => { type Test = string extends typeof keys ? never : "true"; const test: Test = "true"; // ok return { test }; },}) : { schema: { attribute: string; }; toAnswers: (keys: "attribute") => { test: "true"; }; } +> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +>{ schema: { attribute: "anything", }, toAnswers: (keys) => { type Test = string extends typeof keys ? never : "true"; const test: Test = "true"; // ok return { test }; },} : { schema: { attribute: string; }; toAnswers: (keys: "attribute") => { test: "true"; }; } +> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + + schema: { +>schema : { attribute: string; } +> : ^^^^^^^^^^^^^^^^^^^^^^ +>{ attribute: "anything", } : { attribute: string; } +> : ^^^^^^^^^^^^^^^^^^^^^^ + + attribute: "anything", +>attribute : string +> : ^^^^^^ +>"anything" : "anything" +> : ^^^^^^^^^^ + + }, + toAnswers: (keys) => { +>toAnswers : (keys: "attribute") => { test: "true"; } +> : ^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +>(keys) => { type Test = string extends typeof keys ? never : "true"; const test: Test = "true"; // ok return { test }; } : (keys: "attribute") => { test: "true"; } +> : ^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +>keys : "attribute" +> : ^^^^^^^^^^^ + + type Test = string extends typeof keys ? never : "true"; +>Test : "true" +> : ^^^^^^ +>keys : "attribute" +> : ^^^^^^^^^^^ + + const test: Test = "true"; // ok +>test : "true" +> : ^^^^^^ +>"true" : "true" +> : ^^^^^^ + + return { test }; +>{ test } : { test: "true"; } +> : ^^^^^^^^^^^^^^^^^ +>test : "true" +> : ^^^^^^ + + }, +})); + +type StepFunction2 = (anything: unknown) => { +>StepFunction2 : StepFunction2 +> : ^^^^^^^^^^^^^^^^^^^^^^ +>anything : unknown +> : ^^^^^^^ + + readonly schema: (thing: number) => TSchema; +>schema : (thing: number) => TSchema +> : ^ ^^ ^^^^^ +>thing : number +> : ^^^^^^ + + readonly toAnswers?: (keys: keyof TSchema) => unknown; +>toAnswers : ((keys: keyof TSchema) => unknown) | undefined +> : ^^ ^^ ^^^^^ ^^^^^^^^^^^^^ +>keys : keyof TSchema +> : ^^^^^^^^^^^^^ + +}; + +function step2( +>step2 : (stepVal: StepFunction2) => StepFunction2 +> : ^ ^^^^^^^^^ ^^^^^^^^^^^ ^^ ^^^^^ + + stepVal: StepFunction2, +>stepVal : StepFunction2 +> : ^^^^^^^^^^^^^^^^^^^^^^ + +): StepFunction2 { + return stepVal; +>stepVal : StepFunction2 +> : ^^^^^^^^^^^^^^^^^^^^^^ +} + +const stepResult2 = step2((_something) => ({ +>stepResult2 : StepFunction2<{ attribute: string; }> +> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +>step2((_something) => ({ schema: (thing) => ({ attribute: "anything", }), toAnswers: (keys) => { type Test = string extends typeof keys ? never : "true"; const test: Test = "true"; // ok return { test }; },})) : StepFunction2<{ attribute: string; }> +> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +>step2 : (stepVal: StepFunction2) => StepFunction2 +> : ^ ^^^^^^^^^ ^^^^^^^^^^^ ^^ ^^^^^ +>(_something) => ({ schema: (thing) => ({ attribute: "anything", }), toAnswers: (keys) => { type Test = string extends typeof keys ? never : "true"; const test: Test = "true"; // ok return { test }; },}) : (_something: unknown) => { schema: (thing: number) => { attribute: string; }; toAnswers: (keys: "attribute") => { test: "true"; }; } +> : ^ ^^^^^^^^^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +>_something : unknown +> : ^^^^^^^ +>({ schema: (thing) => ({ attribute: "anything", }), toAnswers: (keys) => { type Test = string extends typeof keys ? never : "true"; const test: Test = "true"; // ok return { test }; },}) : { schema: (thing: number) => { attribute: string; }; toAnswers: (keys: "attribute") => { test: "true"; }; } +> : ^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +>{ schema: (thing) => ({ attribute: "anything", }), toAnswers: (keys) => { type Test = string extends typeof keys ? never : "true"; const test: Test = "true"; // ok return { test }; },} : { schema: (thing: number) => { attribute: string; }; toAnswers: (keys: "attribute") => { test: "true"; }; } +> : ^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + + schema: (thing) => ({ +>schema : (thing: number) => { attribute: string; } +> : ^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +>(thing) => ({ attribute: "anything", }) : (thing: number) => { attribute: string; } +> : ^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +>thing : number +> : ^^^^^^ +>({ attribute: "anything", }) : { attribute: string; } +> : ^^^^^^^^^^^^^^^^^^^^^^ +>{ attribute: "anything", } : { attribute: string; } +> : ^^^^^^^^^^^^^^^^^^^^^^ + + attribute: "anything", +>attribute : string +> : ^^^^^^ +>"anything" : "anything" +> : ^^^^^^^^^^ + + }), + toAnswers: (keys) => { +>toAnswers : (keys: "attribute") => { test: "true"; } +> : ^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +>(keys) => { type Test = string extends typeof keys ? never : "true"; const test: Test = "true"; // ok return { test }; } : (keys: "attribute") => { test: "true"; } +> : ^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +>keys : "attribute" +> : ^^^^^^^^^^^ + + type Test = string extends typeof keys ? never : "true"; +>Test : "true" +> : ^^^^^^ +>keys : "attribute" +> : ^^^^^^^^^^^ + + const test: Test = "true"; // ok +>test : "true" +> : ^^^^^^ +>"true" : "true" +> : ^^^^^^ + + return { test }; +>{ test } : { test: "true"; } +> : ^^^^^^^^^^^^^^^^^ +>test : "true" +> : ^^^^^^ + + }, +})); + diff --git a/tests/cases/conformance/types/typeRelationships/typeInference/intraExpressionInferencesInContextSensitive1.ts b/tests/cases/conformance/types/typeRelationships/typeInference/intraExpressionInferencesInContextSensitive1.ts new file mode 100644 index 0000000000000..e8de5fcbcafe6 --- /dev/null +++ b/tests/cases/conformance/types/typeRelationships/typeInference/intraExpressionInferencesInContextSensitive1.ts @@ -0,0 +1,76 @@ +// @strict: true +// @declaration: true + +// https://github.com/microsoft/TypeScript/issues/60720 + +type Options = { + onStart?: () => TContext; + onEnd?: (context: TContext) => void; +}; + +function create(builder: (arg: boolean) => Options) { + return builder(true); +} + +create((arg: boolean) => ({ + onStart: () => ({ time: new Date() }), + onEnd: (context) => {}, +})); + +create(() => ({ + onStart: () => ({ time: new Date() }), + onEnd: (context) => {}, +})); + +create((arg) => ({ + onStart: () => ({ time: new Date() }), + onEnd: (context) => {}, +})); + +// https://github.com/microsoft/TypeScript/issues/57021 + +type Schema = Record; + +type StepFunction = (anything: unknown) => { + readonly schema: TSchema; + readonly toAnswers?: (keys: keyof TSchema) => unknown; +}; + +function step1( + stepVal: StepFunction, +): StepFunction { + return stepVal; +} + +const stepResult1 = step1((_something) => ({ + schema: { + attribute: "anything", + }, + toAnswers: (keys) => { + type Test = string extends typeof keys ? never : "true"; + const test: Test = "true"; // ok + return { test }; + }, +})); + +type StepFunction2 = (anything: unknown) => { + readonly schema: (thing: number) => TSchema; + readonly toAnswers?: (keys: keyof TSchema) => unknown; +}; + +function step2( + stepVal: StepFunction2, +): StepFunction2 { + return stepVal; +} + +const stepResult2 = step2((_something) => ({ + schema: (thing) => ({ + attribute: "anything", + }), + toAnswers: (keys) => { + type Test = string extends typeof keys ? never : "true"; + const test: Test = "true"; // ok + return { test }; + }, +})); From 7ccc000c36a48d4781dc845e5bc56500757fde4e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mateusz=20Burzy=C5=84ski?= Date: Fri, 3 Jan 2025 10:45:38 +0100 Subject: [PATCH 2/8] update baselines --- .../reference/genericCallWithFunctionTypedArguments.types | 8 ++++---- .../genericClassWithFunctionTypedMemberArguments.types | 8 ++++---- .../jsxChildrenGenericContextualTypes.errors.txt | 4 ++-- 3 files changed, 10 insertions(+), 10 deletions(-) diff --git a/tests/baselines/reference/genericCallWithFunctionTypedArguments.types b/tests/baselines/reference/genericCallWithFunctionTypedArguments.types index a73ea35f76703..560a592a81798 100644 --- a/tests/baselines/reference/genericCallWithFunctionTypedArguments.types +++ b/tests/baselines/reference/genericCallWithFunctionTypedArguments.types @@ -20,10 +20,10 @@ function foo(x: (a: T) => T) { } var r = foo((x: U) => ''); // {} ->r : unknown -> : ^^^^^^^ ->foo((x: U) => '') : unknown -> : ^^^^^^^ +>r : string +> : ^^^^^^ +>foo((x: U) => '') : string +> : ^^^^^^ >foo : (x: (a: T) => T) => T > : ^ ^^ ^^ ^^^^^^ >(x: U) => '' : (x: U) => string diff --git a/tests/baselines/reference/genericClassWithFunctionTypedMemberArguments.types b/tests/baselines/reference/genericClassWithFunctionTypedMemberArguments.types index 0b5546dadc22d..c4503de2e9896 100644 --- a/tests/baselines/reference/genericClassWithFunctionTypedMemberArguments.types +++ b/tests/baselines/reference/genericClassWithFunctionTypedMemberArguments.types @@ -37,10 +37,10 @@ module ImmediatelyFix { > : ^^^^^^^^ var r = c.foo((x: U) => ''); // {} ->r : unknown -> : ^^^^^^^ ->c.foo((x: U) => '') : unknown -> : ^^^^^^^ +>r : string +> : ^^^^^^ +>c.foo((x: U) => '') : string +> : ^^^^^^ >c.foo : (x: (a: T) => T) => T > : ^ ^^ ^^^ ^^^^^^^^^^^^^^^ >c : C diff --git a/tests/baselines/reference/jsxChildrenGenericContextualTypes.errors.txt b/tests/baselines/reference/jsxChildrenGenericContextualTypes.errors.txt index 203736cf69381..4dac0d46e6e74 100644 --- a/tests/baselines/reference/jsxChildrenGenericContextualTypes.errors.txt +++ b/tests/baselines/reference/jsxChildrenGenericContextualTypes.errors.txt @@ -1,6 +1,6 @@ jsxChildrenGenericContextualTypes.tsx(20,46): error TS2322: Type '"y"' is not assignable to type '"x"'. jsxChildrenGenericContextualTypes.tsx(21,42): error TS2322: Type '"y"' is not assignable to type '"x"'. -jsxChildrenGenericContextualTypes.tsx(22,45): error TS2322: Type 'number' is not assignable to type '"x"'. +jsxChildrenGenericContextualTypes.tsx(22,45): error TS2322: Type 'number' is not assignable to type 'string'. ==== jsxChildrenGenericContextualTypes.tsx (3 errors) ==== @@ -33,5 +33,5 @@ jsxChildrenGenericContextualTypes.tsx(22,45): error TS2322: Type 'number' is not !!! related TS6502 jsxChildrenGenericContextualTypes.tsx:13:44: The expected type comes from the return type of this signature. const mismatched = {() => 12} ~~ -!!! error TS2322: Type 'number' is not assignable to type '"x"'. +!!! error TS2322: Type 'number' is not assignable to type 'string'. !!! related TS6502 jsxChildrenGenericContextualTypes.tsx:13:44: The expected type comes from the return type of this signature. \ No newline at end of file From 37af847800ec74df339df0fa2405bf5a28b9805b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mateusz=20Burzy=C5=84ski?= Date: Fri, 3 Jan 2025 10:57:25 +0100 Subject: [PATCH 3/8] fmt --- src/compiler/checker.ts | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 5ba037cb5064a..e87a92355aff8 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -38981,7 +38981,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { if (contextualSignature && !getReturnTypeFromAnnotation(node) && !signature.resolvedReturnType) { let contextualReturnType: Type; let returnType: Type; - + if (checkMode & CheckMode.Inferential && couldContainTypeVariables(contextualReturnType = getReturnTypeOfSignature(contextualSignature))) { const inferenceContext = getInferenceContext(node); const isReturnContextSensitive = !!node.body && (node.body.kind === SyntaxKind.Block ? forEachReturnStatement(node.body as Block, statement => !!statement.expression && isContextSensitive(statement.expression)) : isContextSensitive(node.body)); @@ -38990,10 +38990,11 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { if (isReturnContextSensitive) { returnType = getReturnTypeFromBody(node, checkMode); } - } else { + } + else { returnType = getReturnTypeFromBody(node, checkMode); } - + if (!signature.resolvedReturnType) { signature.resolvedReturnType = returnType; } From 4aa5ca7fef3aad34723bca3888f9ecd610baa7da Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mateusz=20Burzy=C5=84ski?= Date: Fri, 3 Jan 2025 21:45:06 +0100 Subject: [PATCH 4/8] stop redundant inference from returns of non-context sensitive functions --- src/compiler/checker.ts | 10 +- .../genericFunctionInference3.symbols | 111 ++++++++++++++++++ .../reference/genericFunctionInference3.types | 104 ++++++++++++++++ .../compiler/genericFunctionInference3.ts | 43 +++++++ 4 files changed, 262 insertions(+), 6 deletions(-) create mode 100644 tests/baselines/reference/genericFunctionInference3.symbols create mode 100644 tests/baselines/reference/genericFunctionInference3.types create mode 100644 tests/cases/compiler/genericFunctionInference3.ts diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index e87a92355aff8..9af709de21963 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -38952,7 +38952,8 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { if (!signature) { return; } - if (isContextSensitive(node)) { + const isNodeContextSensitive = isContextSensitive(node); + if (isNodeContextSensitive) { if (contextualSignature) { const inferenceContext = getInferenceContext(node); let instantiatedContextualSignature: Signature | undefined; @@ -38982,7 +38983,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { let contextualReturnType: Type; let returnType: Type; - if (checkMode & CheckMode.Inferential && couldContainTypeVariables(contextualReturnType = getReturnTypeOfSignature(contextualSignature))) { + if (isNodeContextSensitive && checkMode & CheckMode.Inferential && couldContainTypeVariables(contextualReturnType = getReturnTypeOfSignature(contextualSignature))) { const inferenceContext = getInferenceContext(node); const isReturnContextSensitive = !!node.body && (node.body.kind === SyntaxKind.Block ? forEachReturnStatement(node.body as Block, statement => !!statement.expression && isContextSensitive(statement.expression)) : isContextSensitive(node.body)); returnType = getReturnTypeFromBody(node, checkMode | (isReturnContextSensitive ? CheckMode.SkipContextSensitive : 0)); @@ -38994,10 +38995,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { else { returnType = getReturnTypeFromBody(node, checkMode); } - - if (!signature.resolvedReturnType) { - signature.resolvedReturnType = returnType; - } + signature.resolvedReturnType ??= returnType; } checkSignatureDeclaration(node); } diff --git a/tests/baselines/reference/genericFunctionInference3.symbols b/tests/baselines/reference/genericFunctionInference3.symbols new file mode 100644 index 0000000000000..9107acf987c2d --- /dev/null +++ b/tests/baselines/reference/genericFunctionInference3.symbols @@ -0,0 +1,111 @@ +//// [tests/cases/compiler/genericFunctionInference3.ts] //// + +=== genericFunctionInference3.ts === +const enum SyntaxKind { +>SyntaxKind : Symbol(SyntaxKind, Decl(genericFunctionInference3.ts, 0, 0)) + + JSDocAllType, +>JSDocAllType : Symbol(SyntaxKind.JSDocAllType, Decl(genericFunctionInference3.ts, 0, 23)) + + JSDocUnknownType, +>JSDocUnknownType : Symbol(SyntaxKind.JSDocUnknownType, Decl(genericFunctionInference3.ts, 1, 15)) +} + +interface Node { +>Node : Symbol(Node, Decl(genericFunctionInference3.ts, 3, 1)) + + readonly kind: SyntaxKind; +>kind : Symbol(Node.kind, Decl(genericFunctionInference3.ts, 5, 16)) +>SyntaxKind : Symbol(SyntaxKind, Decl(genericFunctionInference3.ts, 0, 0)) +} + +interface TypeNode extends Node { +>TypeNode : Symbol(TypeNode, Decl(genericFunctionInference3.ts, 7, 1)) +>Node : Symbol(Node, Decl(genericFunctionInference3.ts, 3, 1)) + + _typeNodeBrand: any; +>_typeNodeBrand : Symbol(TypeNode._typeNodeBrand, Decl(genericFunctionInference3.ts, 9, 33)) +} + +interface JSDocType extends TypeNode { +>JSDocType : Symbol(JSDocType, Decl(genericFunctionInference3.ts, 11, 1)) +>TypeNode : Symbol(TypeNode, Decl(genericFunctionInference3.ts, 7, 1)) + + _jsDocTypeBrand: any; +>_jsDocTypeBrand : Symbol(JSDocType._jsDocTypeBrand, Decl(genericFunctionInference3.ts, 13, 38)) +} + +export interface JSDocAllType extends JSDocType { +>JSDocAllType : Symbol(JSDocAllType, Decl(genericFunctionInference3.ts, 15, 1)) +>JSDocType : Symbol(JSDocType, Decl(genericFunctionInference3.ts, 11, 1)) + + readonly kind: SyntaxKind.JSDocAllType; +>kind : Symbol(JSDocAllType.kind, Decl(genericFunctionInference3.ts, 17, 49)) +>SyntaxKind : Symbol(SyntaxKind, Decl(genericFunctionInference3.ts, 0, 0)) +>JSDocAllType : Symbol(SyntaxKind.JSDocAllType, Decl(genericFunctionInference3.ts, 0, 23)) +} + +export interface JSDocUnknownType extends JSDocType { +>JSDocUnknownType : Symbol(JSDocUnknownType, Decl(genericFunctionInference3.ts, 19, 1)) +>JSDocType : Symbol(JSDocType, Decl(genericFunctionInference3.ts, 11, 1)) + + readonly kind: SyntaxKind.JSDocUnknownType; +>kind : Symbol(JSDocUnknownType.kind, Decl(genericFunctionInference3.ts, 21, 53)) +>SyntaxKind : Symbol(SyntaxKind, Decl(genericFunctionInference3.ts, 0, 0)) +>JSDocUnknownType : Symbol(SyntaxKind.JSDocUnknownType, Decl(genericFunctionInference3.ts, 1, 15)) +} + +type Mutable = { -readonly [K in keyof T]: T[K] }; +>Mutable : Symbol(Mutable, Decl(genericFunctionInference3.ts, 23, 1)) +>T : Symbol(T, Decl(genericFunctionInference3.ts, 25, 13)) +>K : Symbol(K, Decl(genericFunctionInference3.ts, 25, 46)) +>T : Symbol(T, Decl(genericFunctionInference3.ts, 25, 13)) +>T : Symbol(T, Decl(genericFunctionInference3.ts, 25, 13)) +>K : Symbol(K, Decl(genericFunctionInference3.ts, 25, 46)) + +declare function createJSDocPrimaryTypeWorker( +>createJSDocPrimaryTypeWorker : Symbol(createJSDocPrimaryTypeWorker, Decl(genericFunctionInference3.ts, 25, 68)) +>T : Symbol(T, Decl(genericFunctionInference3.ts, 27, 46)) +>JSDocType : Symbol(JSDocType, Decl(genericFunctionInference3.ts, 11, 1)) + + kind: T["kind"], +>kind : Symbol(kind, Decl(genericFunctionInference3.ts, 27, 67)) +>T : Symbol(T, Decl(genericFunctionInference3.ts, 27, 46)) + +): Mutable; +>Mutable : Symbol(Mutable, Decl(genericFunctionInference3.ts, 23, 1)) +>T : Symbol(T, Decl(genericFunctionInference3.ts, 27, 46)) + +declare function memoizeOne( +>memoizeOne : Symbol(memoizeOne, Decl(genericFunctionInference3.ts, 29, 14)) +>A : Symbol(A, Decl(genericFunctionInference3.ts, 31, 28)) +>T : Symbol(T, Decl(genericFunctionInference3.ts, 31, 76)) + + callback: (arg: A) => T, +>callback : Symbol(callback, Decl(genericFunctionInference3.ts, 31, 80)) +>arg : Symbol(arg, Decl(genericFunctionInference3.ts, 32, 13)) +>A : Symbol(A, Decl(genericFunctionInference3.ts, 31, 28)) +>T : Symbol(T, Decl(genericFunctionInference3.ts, 31, 76)) + +): (arg: A) => T; +>arg : Symbol(arg, Decl(genericFunctionInference3.ts, 33, 4)) +>A : Symbol(A, Decl(genericFunctionInference3.ts, 31, 28)) +>T : Symbol(T, Decl(genericFunctionInference3.ts, 31, 76)) + +export const getJSDocPrimaryTypeCreateFunction = memoizeOne( +>getJSDocPrimaryTypeCreateFunction : Symbol(getJSDocPrimaryTypeCreateFunction, Decl(genericFunctionInference3.ts, 35, 12)) +>memoizeOne : Symbol(memoizeOne, Decl(genericFunctionInference3.ts, 29, 14)) + + (kind: T["kind"]) => +>T : Symbol(T, Decl(genericFunctionInference3.ts, 36, 3)) +>JSDocType : Symbol(JSDocType, Decl(genericFunctionInference3.ts, 11, 1)) +>kind : Symbol(kind, Decl(genericFunctionInference3.ts, 36, 24)) +>T : Symbol(T, Decl(genericFunctionInference3.ts, 36, 3)) + + () => + createJSDocPrimaryTypeWorker(kind), +>createJSDocPrimaryTypeWorker : Symbol(createJSDocPrimaryTypeWorker, Decl(genericFunctionInference3.ts, 25, 68)) +>kind : Symbol(kind, Decl(genericFunctionInference3.ts, 36, 24)) + +); + diff --git a/tests/baselines/reference/genericFunctionInference3.types b/tests/baselines/reference/genericFunctionInference3.types new file mode 100644 index 0000000000000..a20572c980794 --- /dev/null +++ b/tests/baselines/reference/genericFunctionInference3.types @@ -0,0 +1,104 @@ +//// [tests/cases/compiler/genericFunctionInference3.ts] //// + +=== genericFunctionInference3.ts === +const enum SyntaxKind { +>SyntaxKind : SyntaxKind +> : ^^^^^^^^^^ + + JSDocAllType, +>JSDocAllType : SyntaxKind.JSDocAllType +> : ^^^^^^^^^^^^^^^^^^^^^^^ + + JSDocUnknownType, +>JSDocUnknownType : SyntaxKind.JSDocUnknownType +> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^ +} + +interface Node { + readonly kind: SyntaxKind; +>kind : SyntaxKind +> : ^^^^^^^^^^ +} + +interface TypeNode extends Node { + _typeNodeBrand: any; +>_typeNodeBrand : any +} + +interface JSDocType extends TypeNode { + _jsDocTypeBrand: any; +>_jsDocTypeBrand : any +} + +export interface JSDocAllType extends JSDocType { + readonly kind: SyntaxKind.JSDocAllType; +>kind : SyntaxKind.JSDocAllType +> : ^^^^^^^^^^^^^^^^^^^^^^^ +>SyntaxKind : any +> : ^^^ +} + +export interface JSDocUnknownType extends JSDocType { + readonly kind: SyntaxKind.JSDocUnknownType; +>kind : SyntaxKind.JSDocUnknownType +> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^ +>SyntaxKind : any +> : ^^^ +} + +type Mutable = { -readonly [K in keyof T]: T[K] }; +>Mutable : Mutable +> : ^^^^^^^^^^ + +declare function createJSDocPrimaryTypeWorker( +>createJSDocPrimaryTypeWorker : (kind: T["kind"]) => Mutable +> : ^ ^^^^^^^^^ ^^ ^^ ^^^^^ + + kind: T["kind"], +>kind : T["kind"] +> : ^^^^^^^^^ + +): Mutable; + +declare function memoizeOne( +>memoizeOne : (callback: (arg: A) => T) => (arg: A) => T +> : ^ ^^^^^^^^^ ^^ ^^ ^^ ^^^^^ + + callback: (arg: A) => T, +>callback : (arg: A) => T +> : ^ ^^ ^^^^^ +>arg : A +> : ^ + +): (arg: A) => T; +>arg : A +> : ^ + +export const getJSDocPrimaryTypeCreateFunction = memoizeOne( +>getJSDocPrimaryTypeCreateFunction : (arg: T["kind"]) => () => Mutable +> : ^ ^^^^^^^^^ ^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +>memoizeOne( (kind: T["kind"]) => () => createJSDocPrimaryTypeWorker(kind),) : (arg: T["kind"]) => () => Mutable +> : ^ ^^^^^^^^^ ^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +>memoizeOne : (callback: (arg: A) => T) => (arg: A) => T +> : ^ ^^^^^^^^^ ^^ ^^ ^^ ^^^^^ + + (kind: T["kind"]) => +>(kind: T["kind"]) => () => createJSDocPrimaryTypeWorker(kind) : (kind: T["kind"]) => () => Mutable +> : ^ ^^^^^^^^^ ^^ ^^ ^^^^^^^^^^^^^^^^^^^^^ +>kind : T["kind"] +> : ^^^^^^^^^ + + () => +>() => createJSDocPrimaryTypeWorker(kind) : () => Mutable +> : ^^^^^^^^^^^^^^^^ + + createJSDocPrimaryTypeWorker(kind), +>createJSDocPrimaryTypeWorker(kind) : Mutable +> : ^^^^^^^^^^ +>createJSDocPrimaryTypeWorker : (kind: T_1["kind"]) => Mutable +> : ^^^^^^^^^^^^^ ^^ ^^ ^^^^^ +>kind : T["kind"] +> : ^^^^^^^^^ + +); + diff --git a/tests/cases/compiler/genericFunctionInference3.ts b/tests/cases/compiler/genericFunctionInference3.ts new file mode 100644 index 0000000000000..79d538f1b28ec --- /dev/null +++ b/tests/cases/compiler/genericFunctionInference3.ts @@ -0,0 +1,43 @@ +// @strict: true +// @noEmit: true + +const enum SyntaxKind { + JSDocAllType, + JSDocUnknownType, +} + +interface Node { + readonly kind: SyntaxKind; +} + +interface TypeNode extends Node { + _typeNodeBrand: any; +} + +interface JSDocType extends TypeNode { + _jsDocTypeBrand: any; +} + +export interface JSDocAllType extends JSDocType { + readonly kind: SyntaxKind.JSDocAllType; +} + +export interface JSDocUnknownType extends JSDocType { + readonly kind: SyntaxKind.JSDocUnknownType; +} + +type Mutable = { -readonly [K in keyof T]: T[K] }; + +declare function createJSDocPrimaryTypeWorker( + kind: T["kind"], +): Mutable; + +declare function memoizeOne( + callback: (arg: A) => T, +): (arg: A) => T; + +export const getJSDocPrimaryTypeCreateFunction = memoizeOne( + (kind: T["kind"]) => + () => + createJSDocPrimaryTypeWorker(kind), +); From 3095dad4e5d0256dfbc761ff95e2d4afec9250ee Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mateusz=20Burzy=C5=84ski?= Date: Fri, 3 Jan 2025 23:58:49 +0100 Subject: [PATCH 5/8] update baselines --- .../reference/genericCallWithFunctionTypedArguments.types | 8 ++++---- .../genericClassWithFunctionTypedMemberArguments.types | 8 ++++---- .../jsxChildrenGenericContextualTypes.errors.txt | 4 ++-- 3 files changed, 10 insertions(+), 10 deletions(-) diff --git a/tests/baselines/reference/genericCallWithFunctionTypedArguments.types b/tests/baselines/reference/genericCallWithFunctionTypedArguments.types index 560a592a81798..a73ea35f76703 100644 --- a/tests/baselines/reference/genericCallWithFunctionTypedArguments.types +++ b/tests/baselines/reference/genericCallWithFunctionTypedArguments.types @@ -20,10 +20,10 @@ function foo(x: (a: T) => T) { } var r = foo((x: U) => ''); // {} ->r : string -> : ^^^^^^ ->foo((x: U) => '') : string -> : ^^^^^^ +>r : unknown +> : ^^^^^^^ +>foo((x: U) => '') : unknown +> : ^^^^^^^ >foo : (x: (a: T) => T) => T > : ^ ^^ ^^ ^^^^^^ >(x: U) => '' : (x: U) => string diff --git a/tests/baselines/reference/genericClassWithFunctionTypedMemberArguments.types b/tests/baselines/reference/genericClassWithFunctionTypedMemberArguments.types index c4503de2e9896..0b5546dadc22d 100644 --- a/tests/baselines/reference/genericClassWithFunctionTypedMemberArguments.types +++ b/tests/baselines/reference/genericClassWithFunctionTypedMemberArguments.types @@ -37,10 +37,10 @@ module ImmediatelyFix { > : ^^^^^^^^ var r = c.foo((x: U) => ''); // {} ->r : string -> : ^^^^^^ ->c.foo((x: U) => '') : string -> : ^^^^^^ +>r : unknown +> : ^^^^^^^ +>c.foo((x: U) => '') : unknown +> : ^^^^^^^ >c.foo : (x: (a: T) => T) => T > : ^ ^^ ^^^ ^^^^^^^^^^^^^^^ >c : C diff --git a/tests/baselines/reference/jsxChildrenGenericContextualTypes.errors.txt b/tests/baselines/reference/jsxChildrenGenericContextualTypes.errors.txt index 4dac0d46e6e74..203736cf69381 100644 --- a/tests/baselines/reference/jsxChildrenGenericContextualTypes.errors.txt +++ b/tests/baselines/reference/jsxChildrenGenericContextualTypes.errors.txt @@ -1,6 +1,6 @@ jsxChildrenGenericContextualTypes.tsx(20,46): error TS2322: Type '"y"' is not assignable to type '"x"'. jsxChildrenGenericContextualTypes.tsx(21,42): error TS2322: Type '"y"' is not assignable to type '"x"'. -jsxChildrenGenericContextualTypes.tsx(22,45): error TS2322: Type 'number' is not assignable to type 'string'. +jsxChildrenGenericContextualTypes.tsx(22,45): error TS2322: Type 'number' is not assignable to type '"x"'. ==== jsxChildrenGenericContextualTypes.tsx (3 errors) ==== @@ -33,5 +33,5 @@ jsxChildrenGenericContextualTypes.tsx(22,45): error TS2322: Type 'number' is not !!! related TS6502 jsxChildrenGenericContextualTypes.tsx:13:44: The expected type comes from the return type of this signature. const mismatched = {() => 12} ~~ -!!! error TS2322: Type 'number' is not assignable to type 'string'. +!!! error TS2322: Type 'number' is not assignable to type '"x"'. !!! related TS6502 jsxChildrenGenericContextualTypes.tsx:13:44: The expected type comes from the return type of this signature. \ No newline at end of file From c671b458493e17c72e2dbd3910255aeaccbd7100 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mateusz=20Burzy=C5=84ski?= Date: Sat, 4 Jan 2025 20:15:57 +0100 Subject: [PATCH 6/8] add `CheckMode.SkipReturnTypeFromBodyInference` --- src/compiler/checker.ts | 18 +++++-- .../genericFunctionInference4.symbols | 44 +++++++++++++++ .../reference/genericFunctionInference4.types | 54 +++++++++++++++++++ .../genericFunctionInference5.symbols | 44 +++++++++++++++ .../reference/genericFunctionInference5.types | 54 +++++++++++++++++++ .../compiler/genericFunctionInference4.ts | 14 +++++ .../compiler/genericFunctionInference5.ts | 14 +++++ 7 files changed, 238 insertions(+), 4 deletions(-) create mode 100644 tests/baselines/reference/genericFunctionInference4.symbols create mode 100644 tests/baselines/reference/genericFunctionInference4.types create mode 100644 tests/baselines/reference/genericFunctionInference5.symbols create mode 100644 tests/baselines/reference/genericFunctionInference5.types create mode 100644 tests/cases/compiler/genericFunctionInference4.ts create mode 100644 tests/cases/compiler/genericFunctionInference5.ts diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 9af709de21963..e9e54d8be1913 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -1329,11 +1329,14 @@ 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 - IsForSignatureHelp = 1 << 4, // Call resolution for purposes of signature help - RestBindingElement = 1 << 5, // Checking a type that is going to be used to determine the type of a rest binding element + SkipReturnTypeFromBodyInference = 1 << 4, // Skip inferring from return types of context sensitive functions + // it's used to prevent inferring within return types of generic functions, + // as that could create overlapping inferences that would interfere with the logic `instantiateTypeWithSingleGenericCallSignature` that handles them better + IsForSignatureHelp = 1 << 5, // Call resolution for purposes of signature help + 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 << 6, // Called from getTypeOfExpression, diagnostics may be omitted + TypeOnly = 1 << 7, // Called from getTypeOfExpression, diagnostics may be omitted } /** @internal */ @@ -38983,7 +38986,14 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { let contextualReturnType: Type; let returnType: Type; - if (isNodeContextSensitive && checkMode & CheckMode.Inferential && couldContainTypeVariables(contextualReturnType = getReturnTypeOfSignature(contextualSignature))) { + if (node.typeParameters) { + checkMode |= CheckMode.SkipReturnTypeFromBodyInference; + } + + if ( + isNodeContextSensitive && ((checkMode & (CheckMode.Inferential | CheckMode.SkipReturnTypeFromBodyInference)) === CheckMode.Inferential) && + couldContainTypeVariables(contextualReturnType = getReturnTypeOfSignature(contextualSignature)) + ) { const inferenceContext = getInferenceContext(node); const isReturnContextSensitive = !!node.body && (node.body.kind === SyntaxKind.Block ? forEachReturnStatement(node.body as Block, statement => !!statement.expression && isContextSensitive(statement.expression)) : isContextSensitive(node.body)); returnType = getReturnTypeFromBody(node, checkMode | (isReturnContextSensitive ? CheckMode.SkipContextSensitive : 0)); diff --git a/tests/baselines/reference/genericFunctionInference4.symbols b/tests/baselines/reference/genericFunctionInference4.symbols new file mode 100644 index 0000000000000..51bb4e8378ffe --- /dev/null +++ b/tests/baselines/reference/genericFunctionInference4.symbols @@ -0,0 +1,44 @@ +//// [tests/cases/compiler/genericFunctionInference4.ts] //// + +=== genericFunctionInference4.ts === +declare function inner(kind: T): T; +>inner : Symbol(inner, Decl(genericFunctionInference4.ts, 0, 0)) +>T : Symbol(T, Decl(genericFunctionInference4.ts, 0, 23)) +>kind : Symbol(kind, Decl(genericFunctionInference4.ts, 0, 26)) +>T : Symbol(T, Decl(genericFunctionInference4.ts, 0, 23)) +>T : Symbol(T, Decl(genericFunctionInference4.ts, 0, 23)) + +declare function outer( +>outer : Symbol(outer, Decl(genericFunctionInference4.ts, 0, 38)) +>A : Symbol(A, Decl(genericFunctionInference4.ts, 2, 23)) +>T : Symbol(T, Decl(genericFunctionInference4.ts, 2, 49)) + + callback: (arg: A) => (num: number) => T, +>callback : Symbol(callback, Decl(genericFunctionInference4.ts, 2, 53)) +>arg : Symbol(arg, Decl(genericFunctionInference4.ts, 3, 13)) +>A : Symbol(A, Decl(genericFunctionInference4.ts, 2, 23)) +>num : Symbol(num, Decl(genericFunctionInference4.ts, 3, 25)) +>T : Symbol(T, Decl(genericFunctionInference4.ts, 2, 49)) + +): (arg: A) => T; +>arg : Symbol(arg, Decl(genericFunctionInference4.ts, 4, 4)) +>A : Symbol(A, Decl(genericFunctionInference4.ts, 2, 23)) +>T : Symbol(T, Decl(genericFunctionInference4.ts, 2, 49)) + +export const result = outer( +>result : Symbol(result, Decl(genericFunctionInference4.ts, 6, 12)) +>outer : Symbol(outer, Decl(genericFunctionInference4.ts, 0, 38)) + + (arg: T) => +>T : Symbol(T, Decl(genericFunctionInference4.ts, 7, 3)) +>arg : Symbol(arg, Decl(genericFunctionInference4.ts, 7, 21)) +>T : Symbol(T, Decl(genericFunctionInference4.ts, 7, 3)) + + (num) => +>num : Symbol(num, Decl(genericFunctionInference4.ts, 8, 5)) + + inner(arg), +>inner : Symbol(inner, Decl(genericFunctionInference4.ts, 0, 0)) +>arg : Symbol(arg, Decl(genericFunctionInference4.ts, 7, 21)) + +); diff --git a/tests/baselines/reference/genericFunctionInference4.types b/tests/baselines/reference/genericFunctionInference4.types new file mode 100644 index 0000000000000..6a9da160d3ef7 --- /dev/null +++ b/tests/baselines/reference/genericFunctionInference4.types @@ -0,0 +1,54 @@ +//// [tests/cases/compiler/genericFunctionInference4.ts] //// + +=== genericFunctionInference4.ts === +declare function inner(kind: T): T; +>inner : (kind: T) => T +> : ^ ^^ ^^ ^^^^^ +>kind : T +> : ^ + +declare function outer( +>outer : (callback: (arg: A) => (num: number) => T) => (arg: A) => T +> : ^ ^^^^^^^^^ ^^ ^^ ^^ ^^^^^ + + callback: (arg: A) => (num: number) => T, +>callback : (arg: A) => (num: number) => T +> : ^ ^^ ^^^^^ +>arg : A +> : ^ +>num : number +> : ^^^^^^ + +): (arg: A) => T; +>arg : A +> : ^ + +export const result = outer( +>result : (arg: T) => T +> : ^ ^^^^^^^^^ ^^ ^^^^^^^^^ +>outer( (arg: T) => (num) => inner(arg),) : (arg: T) => T +> : ^ ^^^^^^^^^ ^^ ^^^^^^^^^ +>outer : (callback: (arg: A) => (num: number) => T) => (arg: A) => T +> : ^ ^^^^^^^^^ ^^ ^^ ^^ ^^^^^ + + (arg: T) => +>(arg: T) => (num) => inner(arg) : (arg: T) => (num: number) => T +> : ^ ^^^^^^^^^ ^^ ^^ ^^^^^^ ^^^^^^^^^^^^^^ +>arg : T +> : ^ + + (num) => +>(num) => inner(arg) : (num: number) => T +> : ^ ^^^^^^^^^^^^^^ +>num : number +> : ^^^^^^ + + inner(arg), +>inner(arg) : T +> : ^ +>inner : (kind: T_1) => T_1 +> : ^^^^^^ ^^ ^^^^^ +>arg : T +> : ^ + +); diff --git a/tests/baselines/reference/genericFunctionInference5.symbols b/tests/baselines/reference/genericFunctionInference5.symbols new file mode 100644 index 0000000000000..3be2e185841c7 --- /dev/null +++ b/tests/baselines/reference/genericFunctionInference5.symbols @@ -0,0 +1,44 @@ +//// [tests/cases/compiler/genericFunctionInference5.ts] //// + +=== genericFunctionInference5.ts === +declare function inner(kind: T): T; +>inner : Symbol(inner, Decl(genericFunctionInference5.ts, 0, 0)) +>T : Symbol(T, Decl(genericFunctionInference5.ts, 0, 23)) +>kind : Symbol(kind, Decl(genericFunctionInference5.ts, 0, 26)) +>T : Symbol(T, Decl(genericFunctionInference5.ts, 0, 23)) +>T : Symbol(T, Decl(genericFunctionInference5.ts, 0, 23)) + +declare function outer( +>outer : Symbol(outer, Decl(genericFunctionInference5.ts, 0, 38)) +>A : Symbol(A, Decl(genericFunctionInference5.ts, 2, 23)) +>T : Symbol(T, Decl(genericFunctionInference5.ts, 2, 49)) + + callback: (num: number) => (arg: A) => T, +>callback : Symbol(callback, Decl(genericFunctionInference5.ts, 2, 53)) +>num : Symbol(num, Decl(genericFunctionInference5.ts, 3, 13)) +>arg : Symbol(arg, Decl(genericFunctionInference5.ts, 3, 30)) +>A : Symbol(A, Decl(genericFunctionInference5.ts, 2, 23)) +>T : Symbol(T, Decl(genericFunctionInference5.ts, 2, 49)) + +): (arg: A) => T; +>arg : Symbol(arg, Decl(genericFunctionInference5.ts, 4, 4)) +>A : Symbol(A, Decl(genericFunctionInference5.ts, 2, 23)) +>T : Symbol(T, Decl(genericFunctionInference5.ts, 2, 49)) + +export const result = outer( +>result : Symbol(result, Decl(genericFunctionInference5.ts, 6, 12)) +>outer : Symbol(outer, Decl(genericFunctionInference5.ts, 0, 38)) + + (num) => +>num : Symbol(num, Decl(genericFunctionInference5.ts, 7, 3)) + + (arg: T) => +>T : Symbol(T, Decl(genericFunctionInference5.ts, 8, 5)) +>arg : Symbol(arg, Decl(genericFunctionInference5.ts, 8, 23)) +>T : Symbol(T, Decl(genericFunctionInference5.ts, 8, 5)) + + inner(arg), +>inner : Symbol(inner, Decl(genericFunctionInference5.ts, 0, 0)) +>arg : Symbol(arg, Decl(genericFunctionInference5.ts, 8, 23)) + +); diff --git a/tests/baselines/reference/genericFunctionInference5.types b/tests/baselines/reference/genericFunctionInference5.types new file mode 100644 index 0000000000000..4f99efc2fd20c --- /dev/null +++ b/tests/baselines/reference/genericFunctionInference5.types @@ -0,0 +1,54 @@ +//// [tests/cases/compiler/genericFunctionInference5.ts] //// + +=== genericFunctionInference5.ts === +declare function inner(kind: T): T; +>inner : (kind: T) => T +> : ^ ^^ ^^ ^^^^^ +>kind : T +> : ^ + +declare function outer( +>outer : (callback: (num: number) => (arg: A) => T) => (arg: A) => T +> : ^ ^^^^^^^^^ ^^ ^^ ^^ ^^^^^ + + callback: (num: number) => (arg: A) => T, +>callback : (num: number) => (arg: A) => T +> : ^ ^^ ^^^^^ +>num : number +> : ^^^^^^ +>arg : A +> : ^ + +): (arg: A) => T; +>arg : A +> : ^ + +export const result = outer( +>result : (arg: T) => T +> : ^ ^^^^^^^^^ ^^ ^^^^^^^^^ +>outer( (num) => (arg: T) => inner(arg),) : (arg: T) => T +> : ^ ^^^^^^^^^ ^^ ^^^^^^^^^ +>outer : (callback: (num: number) => (arg: A) => T) => (arg: A) => T +> : ^ ^^^^^^^^^ ^^ ^^ ^^ ^^^^^ + + (num) => +>(num) => (arg: T) => inner(arg) : (num: number) => (arg: T) => T +> : ^ ^^^^^^^^^^^^^^ ^^ ^^^^^^ +>num : number +> : ^^^^^^ + + (arg: T) => +>(arg: T) => inner(arg) : (arg: T) => T +> : ^ ^^^^^^^^^ ^^ ^^ ^^^^^^ +>arg : T +> : ^ + + inner(arg), +>inner(arg) : T +> : ^ +>inner : (kind: T_1) => T_1 +> : ^^^^^^ ^^ ^^^^^ +>arg : T +> : ^ + +); diff --git a/tests/cases/compiler/genericFunctionInference4.ts b/tests/cases/compiler/genericFunctionInference4.ts new file mode 100644 index 0000000000000..663fd975997ad --- /dev/null +++ b/tests/cases/compiler/genericFunctionInference4.ts @@ -0,0 +1,14 @@ +// @strict: true +// @noEmit: true + +declare function inner(kind: T): T; + +declare function outer( + callback: (arg: A) => (num: number) => T, +): (arg: A) => T; + +export const result = outer( + (arg: T) => + (num) => + inner(arg), +); \ No newline at end of file diff --git a/tests/cases/compiler/genericFunctionInference5.ts b/tests/cases/compiler/genericFunctionInference5.ts new file mode 100644 index 0000000000000..dafce78402ab2 --- /dev/null +++ b/tests/cases/compiler/genericFunctionInference5.ts @@ -0,0 +1,14 @@ +// @strict: true +// @noEmit: true + +declare function inner(kind: T): T; + +declare function outer( + callback: (num: number) => (arg: A) => T, +): (arg: A) => T; + +export const result = outer( + (num) => + (arg: T) => + inner(arg), +); \ No newline at end of file From c61ea39e8ba480686dc316ee6845ce490c3ad957 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mateusz=20Burzy=C5=84ski?= Date: Mon, 6 Jan 2025 10:03:59 +0100 Subject: [PATCH 7/8] split tests --- .../InferFromReturnsInContextSensitive1.js | 85 +++++++ ...nferFromReturnsInContextSensitive1.symbols | 120 +++++++++ .../InferFromReturnsInContextSensitive1.types | 174 +++++++++++++ ...ExpressionInferencesInContextSensitive1.js | 87 +------ ...ssionInferencesInContextSensitive1.symbols | 218 +++++----------- ...ressionInferencesInContextSensitive1.types | 240 +++--------------- .../InferFromReturnsInContextSensitive1.ts | 44 ++++ ...ExpressionInferencesInContextSensitive1.ts | 46 +--- 8 files changed, 535 insertions(+), 479 deletions(-) create mode 100644 tests/baselines/reference/InferFromReturnsInContextSensitive1.js create mode 100644 tests/baselines/reference/InferFromReturnsInContextSensitive1.symbols create mode 100644 tests/baselines/reference/InferFromReturnsInContextSensitive1.types create mode 100644 tests/cases/conformance/types/typeRelationships/typeInference/InferFromReturnsInContextSensitive1.ts diff --git a/tests/baselines/reference/InferFromReturnsInContextSensitive1.js b/tests/baselines/reference/InferFromReturnsInContextSensitive1.js new file mode 100644 index 0000000000000..f62ce1e4fdcbe --- /dev/null +++ b/tests/baselines/reference/InferFromReturnsInContextSensitive1.js @@ -0,0 +1,85 @@ +//// [tests/cases/conformance/types/typeRelationships/typeInference/InferFromReturnsInContextSensitive1.ts] //// + +//// [InferFromReturnsInContextSensitive1.ts] +// https://github.com/microsoft/TypeScript/issues/60720 + +type Options = { + onStart?: () => TContext; + onEnd?: (context: TContext) => void; +}; + +function create(builder: (arg: boolean) => Options) { + return builder(true); +} + +create((arg) => ({ + onStart: () => ({ time: new Date() }), + onEnd: (context) => {}, +})); + +// https://github.com/microsoft/TypeScript/issues/57021 + +type Schema = Record; + +type StepFunction = (anything: unknown) => { + readonly schema: TSchema; + readonly toAnswers?: (keys: keyof TSchema) => unknown; +}; + +function step1( + stepVal: StepFunction, +): StepFunction { + return stepVal; +} + +const stepResult1 = step1((_something) => ({ + schema: { + attribute: "anything", + }, + toAnswers: (keys) => { + type Test = string extends typeof keys ? never : "true"; + const test: Test = "true"; // ok + return { test }; + }, +})); + + +//// [InferFromReturnsInContextSensitive1.js] +"use strict"; +// https://github.com/microsoft/TypeScript/issues/60720 +function create(builder) { + return builder(true); +} +create(function (arg) { return ({ + onStart: function () { return ({ time: new Date() }); }, + onEnd: function (context) { }, +}); }); +function step1(stepVal) { + return stepVal; +} +var stepResult1 = step1(function (_something) { return ({ + schema: { + attribute: "anything", + }, + toAnswers: function (keys) { + var test = "true"; // ok + return { test: test }; + }, +}); }); + + +//// [InferFromReturnsInContextSensitive1.d.ts] +type Options = { + onStart?: () => TContext; + onEnd?: (context: TContext) => void; +}; +declare function create(builder: (arg: boolean) => Options): Options; +type Schema = Record; +type StepFunction = (anything: unknown) => { + readonly schema: TSchema; + readonly toAnswers?: (keys: keyof TSchema) => unknown; +}; +declare function step1(stepVal: StepFunction): StepFunction; +declare const stepResult1: StepFunction<{ + attribute: string; +}>; diff --git a/tests/baselines/reference/InferFromReturnsInContextSensitive1.symbols b/tests/baselines/reference/InferFromReturnsInContextSensitive1.symbols new file mode 100644 index 0000000000000..0ed0951e1caf6 --- /dev/null +++ b/tests/baselines/reference/InferFromReturnsInContextSensitive1.symbols @@ -0,0 +1,120 @@ +//// [tests/cases/conformance/types/typeRelationships/typeInference/InferFromReturnsInContextSensitive1.ts] //// + +=== InferFromReturnsInContextSensitive1.ts === +// https://github.com/microsoft/TypeScript/issues/60720 + +type Options = { +>Options : Symbol(Options, Decl(InferFromReturnsInContextSensitive1.ts, 0, 0)) +>TContext : Symbol(TContext, Decl(InferFromReturnsInContextSensitive1.ts, 2, 13)) + + onStart?: () => TContext; +>onStart : Symbol(onStart, Decl(InferFromReturnsInContextSensitive1.ts, 2, 26)) +>TContext : Symbol(TContext, Decl(InferFromReturnsInContextSensitive1.ts, 2, 13)) + + onEnd?: (context: TContext) => void; +>onEnd : Symbol(onEnd, Decl(InferFromReturnsInContextSensitive1.ts, 3, 27)) +>context : Symbol(context, Decl(InferFromReturnsInContextSensitive1.ts, 4, 11)) +>TContext : Symbol(TContext, Decl(InferFromReturnsInContextSensitive1.ts, 2, 13)) + +}; + +function create(builder: (arg: boolean) => Options) { +>create : Symbol(create, Decl(InferFromReturnsInContextSensitive1.ts, 5, 2)) +>TContext : Symbol(TContext, Decl(InferFromReturnsInContextSensitive1.ts, 7, 16)) +>builder : Symbol(builder, Decl(InferFromReturnsInContextSensitive1.ts, 7, 26)) +>arg : Symbol(arg, Decl(InferFromReturnsInContextSensitive1.ts, 7, 36)) +>Options : Symbol(Options, Decl(InferFromReturnsInContextSensitive1.ts, 0, 0)) +>TContext : Symbol(TContext, Decl(InferFromReturnsInContextSensitive1.ts, 7, 16)) + + return builder(true); +>builder : Symbol(builder, Decl(InferFromReturnsInContextSensitive1.ts, 7, 26)) +} + +create((arg) => ({ +>create : Symbol(create, Decl(InferFromReturnsInContextSensitive1.ts, 5, 2)) +>arg : Symbol(arg, Decl(InferFromReturnsInContextSensitive1.ts, 11, 8)) + + onStart: () => ({ time: new Date() }), +>onStart : Symbol(onStart, Decl(InferFromReturnsInContextSensitive1.ts, 11, 18)) +>time : Symbol(time, Decl(InferFromReturnsInContextSensitive1.ts, 12, 19)) +>Date : Symbol(Date, Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --), Decl(lib.scripthost.d.ts, --, --)) + + onEnd: (context) => {}, +>onEnd : Symbol(onEnd, Decl(InferFromReturnsInContextSensitive1.ts, 12, 40)) +>context : Symbol(context, Decl(InferFromReturnsInContextSensitive1.ts, 13, 10)) + +})); + +// https://github.com/microsoft/TypeScript/issues/57021 + +type Schema = Record; +>Schema : Symbol(Schema, Decl(InferFromReturnsInContextSensitive1.ts, 14, 4)) +>Record : Symbol(Record, Decl(lib.es5.d.ts, --, --)) + +type StepFunction = (anything: unknown) => { +>StepFunction : Symbol(StepFunction, Decl(InferFromReturnsInContextSensitive1.ts, 18, 38)) +>TSchema : Symbol(TSchema, Decl(InferFromReturnsInContextSensitive1.ts, 20, 18)) +>Schema : Symbol(Schema, Decl(InferFromReturnsInContextSensitive1.ts, 14, 4)) +>Schema : Symbol(Schema, Decl(InferFromReturnsInContextSensitive1.ts, 14, 4)) +>anything : Symbol(anything, Decl(InferFromReturnsInContextSensitive1.ts, 20, 54)) + + readonly schema: TSchema; +>schema : Symbol(schema, Decl(InferFromReturnsInContextSensitive1.ts, 20, 77)) +>TSchema : Symbol(TSchema, Decl(InferFromReturnsInContextSensitive1.ts, 20, 18)) + + readonly toAnswers?: (keys: keyof TSchema) => unknown; +>toAnswers : Symbol(toAnswers, Decl(InferFromReturnsInContextSensitive1.ts, 21, 27)) +>keys : Symbol(keys, Decl(InferFromReturnsInContextSensitive1.ts, 22, 24)) +>TSchema : Symbol(TSchema, Decl(InferFromReturnsInContextSensitive1.ts, 20, 18)) + +}; + +function step1( +>step1 : Symbol(step1, Decl(InferFromReturnsInContextSensitive1.ts, 23, 2)) +>TSchema : Symbol(TSchema, Decl(InferFromReturnsInContextSensitive1.ts, 25, 15)) +>Schema : Symbol(Schema, Decl(InferFromReturnsInContextSensitive1.ts, 14, 4)) +>Schema : Symbol(Schema, Decl(InferFromReturnsInContextSensitive1.ts, 14, 4)) + + stepVal: StepFunction, +>stepVal : Symbol(stepVal, Decl(InferFromReturnsInContextSensitive1.ts, 25, 48)) +>StepFunction : Symbol(StepFunction, Decl(InferFromReturnsInContextSensitive1.ts, 18, 38)) +>TSchema : Symbol(TSchema, Decl(InferFromReturnsInContextSensitive1.ts, 25, 15)) + +): StepFunction { +>StepFunction : Symbol(StepFunction, Decl(InferFromReturnsInContextSensitive1.ts, 18, 38)) +>TSchema : Symbol(TSchema, Decl(InferFromReturnsInContextSensitive1.ts, 25, 15)) + + return stepVal; +>stepVal : Symbol(stepVal, Decl(InferFromReturnsInContextSensitive1.ts, 25, 48)) +} + +const stepResult1 = step1((_something) => ({ +>stepResult1 : Symbol(stepResult1, Decl(InferFromReturnsInContextSensitive1.ts, 31, 5)) +>step1 : Symbol(step1, Decl(InferFromReturnsInContextSensitive1.ts, 23, 2)) +>_something : Symbol(_something, Decl(InferFromReturnsInContextSensitive1.ts, 31, 27)) + + schema: { +>schema : Symbol(schema, Decl(InferFromReturnsInContextSensitive1.ts, 31, 44)) + + attribute: "anything", +>attribute : Symbol(attribute, Decl(InferFromReturnsInContextSensitive1.ts, 32, 11)) + + }, + toAnswers: (keys) => { +>toAnswers : Symbol(toAnswers, Decl(InferFromReturnsInContextSensitive1.ts, 34, 4)) +>keys : Symbol(keys, Decl(InferFromReturnsInContextSensitive1.ts, 35, 14)) + + type Test = string extends typeof keys ? never : "true"; +>Test : Symbol(Test, Decl(InferFromReturnsInContextSensitive1.ts, 35, 24)) +>keys : Symbol(keys, Decl(InferFromReturnsInContextSensitive1.ts, 35, 14)) + + const test: Test = "true"; // ok +>test : Symbol(test, Decl(InferFromReturnsInContextSensitive1.ts, 37, 9)) +>Test : Symbol(Test, Decl(InferFromReturnsInContextSensitive1.ts, 35, 24)) + + return { test }; +>test : Symbol(test, Decl(InferFromReturnsInContextSensitive1.ts, 38, 12)) + + }, +})); + diff --git a/tests/baselines/reference/InferFromReturnsInContextSensitive1.types b/tests/baselines/reference/InferFromReturnsInContextSensitive1.types new file mode 100644 index 0000000000000..93de793ca595f --- /dev/null +++ b/tests/baselines/reference/InferFromReturnsInContextSensitive1.types @@ -0,0 +1,174 @@ +//// [tests/cases/conformance/types/typeRelationships/typeInference/InferFromReturnsInContextSensitive1.ts] //// + +=== InferFromReturnsInContextSensitive1.ts === +// https://github.com/microsoft/TypeScript/issues/60720 + +type Options = { +>Options : Options +> : ^^^^^^^^^^^^^^^^^ + + onStart?: () => TContext; +>onStart : (() => TContext) | undefined +> : ^^^^^^^ ^^^^^^^^^^^^^ + + onEnd?: (context: TContext) => void; +>onEnd : ((context: TContext) => void) | undefined +> : ^^ ^^ ^^^^^ ^^^^^^^^^^^^^ +>context : TContext +> : ^^^^^^^^ + +}; + +function create(builder: (arg: boolean) => Options) { +>create : (builder: (arg: boolean) => Options) => Options +> : ^ ^^ ^^ ^^^^^^^^^^^^^^^^^^^^^^ +>builder : (arg: boolean) => Options +> : ^ ^^ ^^^^^ +>arg : boolean +> : ^^^^^^^ + + return builder(true); +>builder(true) : Options +> : ^^^^^^^^^^^^^^^^^ +>builder : (arg: boolean) => Options +> : ^ ^^ ^^^^^ +>true : true +> : ^^^^ +} + +create((arg) => ({ +>create((arg) => ({ onStart: () => ({ time: new Date() }), onEnd: (context) => {},})) : Options<{ time: Date; }> +> : ^^^^^^^^^^^^^^^^^^^^^^^^ +>create : (builder: (arg: boolean) => Options) => Options +> : ^ ^^ ^^ ^^^^^^^^^^^^^^^^^^^^^^ +>(arg) => ({ onStart: () => ({ time: new Date() }), onEnd: (context) => {},}) : (arg: boolean) => { onStart: () => { time: Date; }; onEnd: (context: { time: Date; }) => void; } +> : ^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +>arg : boolean +> : ^^^^^^^ +>({ onStart: () => ({ time: new Date() }), onEnd: (context) => {},}) : { onStart: () => { time: Date; }; onEnd: (context: { time: Date; }) => void; } +> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +>{ onStart: () => ({ time: new Date() }), onEnd: (context) => {},} : { onStart: () => { time: Date; }; onEnd: (context: { time: Date; }) => void; } +> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + + onStart: () => ({ time: new Date() }), +>onStart : () => { time: Date; } +> : ^^^^^^^^^^^^^^^^^^^^^ +>() => ({ time: new Date() }) : () => { time: Date; } +> : ^^^^^^^^^^^^^^^^^^^^^ +>({ time: new Date() }) : { time: Date; } +> : ^^^^^^^^^^^^^^^ +>{ time: new Date() } : { time: Date; } +> : ^^^^^^^^^^^^^^^ +>time : Date +> : ^^^^ +>new Date() : Date +> : ^^^^ +>Date : DateConstructor +> : ^^^^^^^^^^^^^^^ + + onEnd: (context) => {}, +>onEnd : (context: { time: Date; }) => void +> : ^ ^^^^^^^^^^^^^^^^^^^^^^^^^^ +>(context) => {} : (context: { time: Date; }) => void +> : ^ ^^^^^^^^^^^^^^^^^^^^^^^^^^ +>context : { time: Date; } +> : ^^^^^^^^^^^^^^^ + +})); + +// https://github.com/microsoft/TypeScript/issues/57021 + +type Schema = Record; +>Schema : Schema +> : ^^^^^^ + +type StepFunction = (anything: unknown) => { +>StepFunction : StepFunction +> : ^^^^^^^^^^^^^^^^^^^^^ +>anything : unknown +> : ^^^^^^^ + + readonly schema: TSchema; +>schema : TSchema +> : ^^^^^^^ + + readonly toAnswers?: (keys: keyof TSchema) => unknown; +>toAnswers : ((keys: keyof TSchema) => unknown) | undefined +> : ^^ ^^ ^^^^^ ^^^^^^^^^^^^^ +>keys : keyof TSchema +> : ^^^^^^^^^^^^^ + +}; + +function step1( +>step1 : (stepVal: StepFunction) => StepFunction +> : ^ ^^^^^^^^^ ^^^^^^^^^^^ ^^ ^^^^^ + + stepVal: StepFunction, +>stepVal : StepFunction +> : ^^^^^^^^^^^^^^^^^^^^^ + +): StepFunction { + return stepVal; +>stepVal : StepFunction +> : ^^^^^^^^^^^^^^^^^^^^^ +} + +const stepResult1 = step1((_something) => ({ +>stepResult1 : StepFunction<{ attribute: string; }> +> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +>step1((_something) => ({ schema: { attribute: "anything", }, toAnswers: (keys) => { type Test = string extends typeof keys ? never : "true"; const test: Test = "true"; // ok return { test }; },})) : StepFunction<{ attribute: string; }> +> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +>step1 : (stepVal: StepFunction) => StepFunction +> : ^ ^^^^^^^^^ ^^^^^^^^^^^ ^^ ^^^^^ +>(_something) => ({ schema: { attribute: "anything", }, toAnswers: (keys) => { type Test = string extends typeof keys ? never : "true"; const test: Test = "true"; // ok return { test }; },}) : (_something: unknown) => { schema: { attribute: string; }; toAnswers: (keys: "attribute") => { test: "true"; }; } +> : ^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +>_something : unknown +> : ^^^^^^^ +>({ schema: { attribute: "anything", }, toAnswers: (keys) => { type Test = string extends typeof keys ? never : "true"; const test: Test = "true"; // ok return { test }; },}) : { schema: { attribute: string; }; toAnswers: (keys: "attribute") => { test: "true"; }; } +> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +>{ schema: { attribute: "anything", }, toAnswers: (keys) => { type Test = string extends typeof keys ? never : "true"; const test: Test = "true"; // ok return { test }; },} : { schema: { attribute: string; }; toAnswers: (keys: "attribute") => { test: "true"; }; } +> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + + schema: { +>schema : { attribute: string; } +> : ^^^^^^^^^^^^^^^^^^^^^^ +>{ attribute: "anything", } : { attribute: string; } +> : ^^^^^^^^^^^^^^^^^^^^^^ + + attribute: "anything", +>attribute : string +> : ^^^^^^ +>"anything" : "anything" +> : ^^^^^^^^^^ + + }, + toAnswers: (keys) => { +>toAnswers : (keys: "attribute") => { test: "true"; } +> : ^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +>(keys) => { type Test = string extends typeof keys ? never : "true"; const test: Test = "true"; // ok return { test }; } : (keys: "attribute") => { test: "true"; } +> : ^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +>keys : "attribute" +> : ^^^^^^^^^^^ + + type Test = string extends typeof keys ? never : "true"; +>Test : "true" +> : ^^^^^^ +>keys : "attribute" +> : ^^^^^^^^^^^ + + const test: Test = "true"; // ok +>test : "true" +> : ^^^^^^ +>"true" : "true" +> : ^^^^^^ + + return { test }; +>{ test } : { test: "true"; } +> : ^^^^^^^^^^^^^^^^^ +>test : "true" +> : ^^^^^^ + + }, +})); + diff --git a/tests/baselines/reference/intraExpressionInferencesInContextSensitive1.js b/tests/baselines/reference/intraExpressionInferencesInContextSensitive1.js index 1ac170d9174bc..760d687ebc55d 100644 --- a/tests/baselines/reference/intraExpressionInferencesInContextSensitive1.js +++ b/tests/baselines/reference/intraExpressionInferencesInContextSensitive1.js @@ -1,10 +1,8 @@ //// [tests/cases/conformance/types/typeRelationships/typeInference/intraExpressionInferencesInContextSensitive1.ts] //// //// [intraExpressionInferencesInContextSensitive1.ts] -// https://github.com/microsoft/TypeScript/issues/60720 - type Options = { - onStart?: () => TContext; + onStart?: (arg: number) => TContext; onEnd?: (context: TContext) => void; }; @@ -12,59 +10,25 @@ function create(builder: (arg: boolean) => Options) { return builder(true); } -create((arg: boolean) => ({ - onStart: () => ({ time: new Date() }), - onEnd: (context) => {}, -})); - -create(() => ({ - onStart: () => ({ time: new Date() }), - onEnd: (context) => {}, -})); - create((arg) => ({ - onStart: () => ({ time: new Date() }), + onStart: (arg) => ({ time: new Date() }), onEnd: (context) => {}, })); -// https://github.com/microsoft/TypeScript/issues/57021 - type Schema = Record; type StepFunction = (anything: unknown) => { - readonly schema: TSchema; + readonly schema: (thing: number) => TSchema; readonly toAnswers?: (keys: keyof TSchema) => unknown; }; -function step1( +function step( stepVal: StepFunction, ): StepFunction { return stepVal; } -const stepResult1 = step1((_something) => ({ - schema: { - attribute: "anything", - }, - toAnswers: (keys) => { - type Test = string extends typeof keys ? never : "true"; - const test: Test = "true"; // ok - return { test }; - }, -})); - -type StepFunction2 = (anything: unknown) => { - readonly schema: (thing: number) => TSchema; - readonly toAnswers?: (keys: keyof TSchema) => unknown; -}; - -function step2( - stepVal: StepFunction2, -): StepFunction2 { - return stepVal; -} - -const stepResult2 = step2((_something) => ({ +const stepResult = step((_something) => ({ schema: (thing) => ({ attribute: "anything", }), @@ -78,38 +42,17 @@ const stepResult2 = step2((_something) => ({ //// [intraExpressionInferencesInContextSensitive1.js] "use strict"; -// https://github.com/microsoft/TypeScript/issues/60720 function create(builder) { return builder(true); } create(function (arg) { return ({ - onStart: function () { return ({ time: new Date() }); }, + onStart: function (arg) { return ({ time: new Date() }); }, onEnd: function (context) { }, }); }); -create(function () { return ({ - onStart: function () { return ({ time: new Date() }); }, - onEnd: function (context) { }, -}); }); -create(function (arg) { return ({ - onStart: function () { return ({ time: new Date() }); }, - onEnd: function (context) { }, -}); }); -function step1(stepVal) { +function step(stepVal) { return stepVal; } -var stepResult1 = step1(function (_something) { return ({ - schema: { - attribute: "anything", - }, - toAnswers: function (keys) { - var test = "true"; // ok - return { test: test }; - }, -}); }); -function step2(stepVal) { - return stepVal; -} -var stepResult2 = step2(function (_something) { return ({ +var stepResult = step(function (_something) { return ({ schema: function (thing) { return ({ attribute: "anything", }); }, @@ -122,24 +65,16 @@ var stepResult2 = step2(function (_something) { return ({ //// [intraExpressionInferencesInContextSensitive1.d.ts] type Options = { - onStart?: () => TContext; + onStart?: (arg: number) => TContext; onEnd?: (context: TContext) => void; }; declare function create(builder: (arg: boolean) => Options): Options; type Schema = Record; type StepFunction = (anything: unknown) => { - readonly schema: TSchema; - readonly toAnswers?: (keys: keyof TSchema) => unknown; -}; -declare function step1(stepVal: StepFunction): StepFunction; -declare const stepResult1: StepFunction<{ - attribute: string; -}>; -type StepFunction2 = (anything: unknown) => { readonly schema: (thing: number) => TSchema; readonly toAnswers?: (keys: keyof TSchema) => unknown; }; -declare function step2(stepVal: StepFunction2): StepFunction2; -declare const stepResult2: StepFunction2<{ +declare function step(stepVal: StepFunction): StepFunction; +declare const stepResult: StepFunction<{ attribute: string; }>; diff --git a/tests/baselines/reference/intraExpressionInferencesInContextSensitive1.symbols b/tests/baselines/reference/intraExpressionInferencesInContextSensitive1.symbols index db64f13f17225..6b124f51f738c 100644 --- a/tests/baselines/reference/intraExpressionInferencesInContextSensitive1.symbols +++ b/tests/baselines/reference/intraExpressionInferencesInContextSensitive1.symbols @@ -1,217 +1,119 @@ //// [tests/cases/conformance/types/typeRelationships/typeInference/intraExpressionInferencesInContextSensitive1.ts] //// === intraExpressionInferencesInContextSensitive1.ts === -// https://github.com/microsoft/TypeScript/issues/60720 - type Options = { >Options : Symbol(Options, Decl(intraExpressionInferencesInContextSensitive1.ts, 0, 0)) ->TContext : Symbol(TContext, Decl(intraExpressionInferencesInContextSensitive1.ts, 2, 13)) +>TContext : Symbol(TContext, Decl(intraExpressionInferencesInContextSensitive1.ts, 0, 13)) - onStart?: () => TContext; ->onStart : Symbol(onStart, Decl(intraExpressionInferencesInContextSensitive1.ts, 2, 26)) ->TContext : Symbol(TContext, Decl(intraExpressionInferencesInContextSensitive1.ts, 2, 13)) + onStart?: (arg: number) => TContext; +>onStart : Symbol(onStart, Decl(intraExpressionInferencesInContextSensitive1.ts, 0, 26)) +>arg : Symbol(arg, Decl(intraExpressionInferencesInContextSensitive1.ts, 1, 13)) +>TContext : Symbol(TContext, Decl(intraExpressionInferencesInContextSensitive1.ts, 0, 13)) onEnd?: (context: TContext) => void; ->onEnd : Symbol(onEnd, Decl(intraExpressionInferencesInContextSensitive1.ts, 3, 27)) ->context : Symbol(context, Decl(intraExpressionInferencesInContextSensitive1.ts, 4, 11)) ->TContext : Symbol(TContext, Decl(intraExpressionInferencesInContextSensitive1.ts, 2, 13)) +>onEnd : Symbol(onEnd, Decl(intraExpressionInferencesInContextSensitive1.ts, 1, 38)) +>context : Symbol(context, Decl(intraExpressionInferencesInContextSensitive1.ts, 2, 11)) +>TContext : Symbol(TContext, Decl(intraExpressionInferencesInContextSensitive1.ts, 0, 13)) }; function create(builder: (arg: boolean) => Options) { ->create : Symbol(create, Decl(intraExpressionInferencesInContextSensitive1.ts, 5, 2)) ->TContext : Symbol(TContext, Decl(intraExpressionInferencesInContextSensitive1.ts, 7, 16)) ->builder : Symbol(builder, Decl(intraExpressionInferencesInContextSensitive1.ts, 7, 26)) ->arg : Symbol(arg, Decl(intraExpressionInferencesInContextSensitive1.ts, 7, 36)) +>create : Symbol(create, Decl(intraExpressionInferencesInContextSensitive1.ts, 3, 2)) +>TContext : Symbol(TContext, Decl(intraExpressionInferencesInContextSensitive1.ts, 5, 16)) +>builder : Symbol(builder, Decl(intraExpressionInferencesInContextSensitive1.ts, 5, 26)) +>arg : Symbol(arg, Decl(intraExpressionInferencesInContextSensitive1.ts, 5, 36)) >Options : Symbol(Options, Decl(intraExpressionInferencesInContextSensitive1.ts, 0, 0)) ->TContext : Symbol(TContext, Decl(intraExpressionInferencesInContextSensitive1.ts, 7, 16)) +>TContext : Symbol(TContext, Decl(intraExpressionInferencesInContextSensitive1.ts, 5, 16)) return builder(true); ->builder : Symbol(builder, Decl(intraExpressionInferencesInContextSensitive1.ts, 7, 26)) +>builder : Symbol(builder, Decl(intraExpressionInferencesInContextSensitive1.ts, 5, 26)) } -create((arg: boolean) => ({ ->create : Symbol(create, Decl(intraExpressionInferencesInContextSensitive1.ts, 5, 2)) ->arg : Symbol(arg, Decl(intraExpressionInferencesInContextSensitive1.ts, 11, 8)) - - onStart: () => ({ time: new Date() }), ->onStart : Symbol(onStart, Decl(intraExpressionInferencesInContextSensitive1.ts, 11, 27)) ->time : Symbol(time, Decl(intraExpressionInferencesInContextSensitive1.ts, 12, 19)) ->Date : Symbol(Date, Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --), Decl(lib.scripthost.d.ts, --, --)) - - onEnd: (context) => {}, ->onEnd : Symbol(onEnd, Decl(intraExpressionInferencesInContextSensitive1.ts, 12, 40)) ->context : Symbol(context, Decl(intraExpressionInferencesInContextSensitive1.ts, 13, 10)) - -})); - -create(() => ({ ->create : Symbol(create, Decl(intraExpressionInferencesInContextSensitive1.ts, 5, 2)) - - onStart: () => ({ time: new Date() }), ->onStart : Symbol(onStart, Decl(intraExpressionInferencesInContextSensitive1.ts, 16, 15)) ->time : Symbol(time, Decl(intraExpressionInferencesInContextSensitive1.ts, 17, 19)) ->Date : Symbol(Date, Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --), Decl(lib.scripthost.d.ts, --, --)) - - onEnd: (context) => {}, ->onEnd : Symbol(onEnd, Decl(intraExpressionInferencesInContextSensitive1.ts, 17, 40)) ->context : Symbol(context, Decl(intraExpressionInferencesInContextSensitive1.ts, 18, 10)) - -})); - create((arg) => ({ ->create : Symbol(create, Decl(intraExpressionInferencesInContextSensitive1.ts, 5, 2)) ->arg : Symbol(arg, Decl(intraExpressionInferencesInContextSensitive1.ts, 21, 8)) +>create : Symbol(create, Decl(intraExpressionInferencesInContextSensitive1.ts, 3, 2)) +>arg : Symbol(arg, Decl(intraExpressionInferencesInContextSensitive1.ts, 9, 8)) - onStart: () => ({ time: new Date() }), ->onStart : Symbol(onStart, Decl(intraExpressionInferencesInContextSensitive1.ts, 21, 18)) ->time : Symbol(time, Decl(intraExpressionInferencesInContextSensitive1.ts, 22, 19)) + onStart: (arg) => ({ time: new Date() }), +>onStart : Symbol(onStart, Decl(intraExpressionInferencesInContextSensitive1.ts, 9, 18)) +>arg : Symbol(arg, Decl(intraExpressionInferencesInContextSensitive1.ts, 10, 12)) +>time : Symbol(time, Decl(intraExpressionInferencesInContextSensitive1.ts, 10, 22)) >Date : Symbol(Date, Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --), Decl(lib.scripthost.d.ts, --, --)) onEnd: (context) => {}, ->onEnd : Symbol(onEnd, Decl(intraExpressionInferencesInContextSensitive1.ts, 22, 40)) ->context : Symbol(context, Decl(intraExpressionInferencesInContextSensitive1.ts, 23, 10)) +>onEnd : Symbol(onEnd, Decl(intraExpressionInferencesInContextSensitive1.ts, 10, 43)) +>context : Symbol(context, Decl(intraExpressionInferencesInContextSensitive1.ts, 11, 10)) })); -// https://github.com/microsoft/TypeScript/issues/57021 - type Schema = Record; ->Schema : Symbol(Schema, Decl(intraExpressionInferencesInContextSensitive1.ts, 24, 4)) +>Schema : Symbol(Schema, Decl(intraExpressionInferencesInContextSensitive1.ts, 12, 4)) >Record : Symbol(Record, Decl(lib.es5.d.ts, --, --)) type StepFunction = (anything: unknown) => { ->StepFunction : Symbol(StepFunction, Decl(intraExpressionInferencesInContextSensitive1.ts, 28, 38)) ->TSchema : Symbol(TSchema, Decl(intraExpressionInferencesInContextSensitive1.ts, 30, 18)) ->Schema : Symbol(Schema, Decl(intraExpressionInferencesInContextSensitive1.ts, 24, 4)) ->Schema : Symbol(Schema, Decl(intraExpressionInferencesInContextSensitive1.ts, 24, 4)) ->anything : Symbol(anything, Decl(intraExpressionInferencesInContextSensitive1.ts, 30, 54)) +>StepFunction : Symbol(StepFunction, Decl(intraExpressionInferencesInContextSensitive1.ts, 14, 38)) +>TSchema : Symbol(TSchema, Decl(intraExpressionInferencesInContextSensitive1.ts, 16, 18)) +>Schema : Symbol(Schema, Decl(intraExpressionInferencesInContextSensitive1.ts, 12, 4)) +>Schema : Symbol(Schema, Decl(intraExpressionInferencesInContextSensitive1.ts, 12, 4)) +>anything : Symbol(anything, Decl(intraExpressionInferencesInContextSensitive1.ts, 16, 54)) - readonly schema: TSchema; ->schema : Symbol(schema, Decl(intraExpressionInferencesInContextSensitive1.ts, 30, 77)) ->TSchema : Symbol(TSchema, Decl(intraExpressionInferencesInContextSensitive1.ts, 30, 18)) + readonly schema: (thing: number) => TSchema; +>schema : Symbol(schema, Decl(intraExpressionInferencesInContextSensitive1.ts, 16, 77)) +>thing : Symbol(thing, Decl(intraExpressionInferencesInContextSensitive1.ts, 17, 20)) +>TSchema : Symbol(TSchema, Decl(intraExpressionInferencesInContextSensitive1.ts, 16, 18)) readonly toAnswers?: (keys: keyof TSchema) => unknown; ->toAnswers : Symbol(toAnswers, Decl(intraExpressionInferencesInContextSensitive1.ts, 31, 27)) ->keys : Symbol(keys, Decl(intraExpressionInferencesInContextSensitive1.ts, 32, 24)) ->TSchema : Symbol(TSchema, Decl(intraExpressionInferencesInContextSensitive1.ts, 30, 18)) +>toAnswers : Symbol(toAnswers, Decl(intraExpressionInferencesInContextSensitive1.ts, 17, 46)) +>keys : Symbol(keys, Decl(intraExpressionInferencesInContextSensitive1.ts, 18, 24)) +>TSchema : Symbol(TSchema, Decl(intraExpressionInferencesInContextSensitive1.ts, 16, 18)) }; -function step1( ->step1 : Symbol(step1, Decl(intraExpressionInferencesInContextSensitive1.ts, 33, 2)) ->TSchema : Symbol(TSchema, Decl(intraExpressionInferencesInContextSensitive1.ts, 35, 15)) ->Schema : Symbol(Schema, Decl(intraExpressionInferencesInContextSensitive1.ts, 24, 4)) ->Schema : Symbol(Schema, Decl(intraExpressionInferencesInContextSensitive1.ts, 24, 4)) +function step( +>step : Symbol(step, Decl(intraExpressionInferencesInContextSensitive1.ts, 19, 2)) +>TSchema : Symbol(TSchema, Decl(intraExpressionInferencesInContextSensitive1.ts, 21, 14)) +>Schema : Symbol(Schema, Decl(intraExpressionInferencesInContextSensitive1.ts, 12, 4)) +>Schema : Symbol(Schema, Decl(intraExpressionInferencesInContextSensitive1.ts, 12, 4)) stepVal: StepFunction, ->stepVal : Symbol(stepVal, Decl(intraExpressionInferencesInContextSensitive1.ts, 35, 48)) ->StepFunction : Symbol(StepFunction, Decl(intraExpressionInferencesInContextSensitive1.ts, 28, 38)) ->TSchema : Symbol(TSchema, Decl(intraExpressionInferencesInContextSensitive1.ts, 35, 15)) +>stepVal : Symbol(stepVal, Decl(intraExpressionInferencesInContextSensitive1.ts, 21, 47)) +>StepFunction : Symbol(StepFunction, Decl(intraExpressionInferencesInContextSensitive1.ts, 14, 38)) +>TSchema : Symbol(TSchema, Decl(intraExpressionInferencesInContextSensitive1.ts, 21, 14)) ): StepFunction { ->StepFunction : Symbol(StepFunction, Decl(intraExpressionInferencesInContextSensitive1.ts, 28, 38)) ->TSchema : Symbol(TSchema, Decl(intraExpressionInferencesInContextSensitive1.ts, 35, 15)) - - return stepVal; ->stepVal : Symbol(stepVal, Decl(intraExpressionInferencesInContextSensitive1.ts, 35, 48)) -} - -const stepResult1 = step1((_something) => ({ ->stepResult1 : Symbol(stepResult1, Decl(intraExpressionInferencesInContextSensitive1.ts, 41, 5)) ->step1 : Symbol(step1, Decl(intraExpressionInferencesInContextSensitive1.ts, 33, 2)) ->_something : Symbol(_something, Decl(intraExpressionInferencesInContextSensitive1.ts, 41, 27)) - - schema: { ->schema : Symbol(schema, Decl(intraExpressionInferencesInContextSensitive1.ts, 41, 44)) - - attribute: "anything", ->attribute : Symbol(attribute, Decl(intraExpressionInferencesInContextSensitive1.ts, 42, 11)) - - }, - toAnswers: (keys) => { ->toAnswers : Symbol(toAnswers, Decl(intraExpressionInferencesInContextSensitive1.ts, 44, 4)) ->keys : Symbol(keys, Decl(intraExpressionInferencesInContextSensitive1.ts, 45, 14)) - - type Test = string extends typeof keys ? never : "true"; ->Test : Symbol(Test, Decl(intraExpressionInferencesInContextSensitive1.ts, 45, 24)) ->keys : Symbol(keys, Decl(intraExpressionInferencesInContextSensitive1.ts, 45, 14)) - - const test: Test = "true"; // ok ->test : Symbol(test, Decl(intraExpressionInferencesInContextSensitive1.ts, 47, 9)) ->Test : Symbol(Test, Decl(intraExpressionInferencesInContextSensitive1.ts, 45, 24)) - - return { test }; ->test : Symbol(test, Decl(intraExpressionInferencesInContextSensitive1.ts, 48, 12)) - - }, -})); - -type StepFunction2 = (anything: unknown) => { ->StepFunction2 : Symbol(StepFunction2, Decl(intraExpressionInferencesInContextSensitive1.ts, 50, 4)) ->TSchema : Symbol(TSchema, Decl(intraExpressionInferencesInContextSensitive1.ts, 52, 19)) ->Schema : Symbol(Schema, Decl(intraExpressionInferencesInContextSensitive1.ts, 24, 4)) ->Schema : Symbol(Schema, Decl(intraExpressionInferencesInContextSensitive1.ts, 24, 4)) ->anything : Symbol(anything, Decl(intraExpressionInferencesInContextSensitive1.ts, 52, 55)) - - readonly schema: (thing: number) => TSchema; ->schema : Symbol(schema, Decl(intraExpressionInferencesInContextSensitive1.ts, 52, 78)) ->thing : Symbol(thing, Decl(intraExpressionInferencesInContextSensitive1.ts, 53, 20)) ->TSchema : Symbol(TSchema, Decl(intraExpressionInferencesInContextSensitive1.ts, 52, 19)) - - readonly toAnswers?: (keys: keyof TSchema) => unknown; ->toAnswers : Symbol(toAnswers, Decl(intraExpressionInferencesInContextSensitive1.ts, 53, 46)) ->keys : Symbol(keys, Decl(intraExpressionInferencesInContextSensitive1.ts, 54, 24)) ->TSchema : Symbol(TSchema, Decl(intraExpressionInferencesInContextSensitive1.ts, 52, 19)) - -}; - -function step2( ->step2 : Symbol(step2, Decl(intraExpressionInferencesInContextSensitive1.ts, 55, 2)) ->TSchema : Symbol(TSchema, Decl(intraExpressionInferencesInContextSensitive1.ts, 57, 15)) ->Schema : Symbol(Schema, Decl(intraExpressionInferencesInContextSensitive1.ts, 24, 4)) ->Schema : Symbol(Schema, Decl(intraExpressionInferencesInContextSensitive1.ts, 24, 4)) - - stepVal: StepFunction2, ->stepVal : Symbol(stepVal, Decl(intraExpressionInferencesInContextSensitive1.ts, 57, 48)) ->StepFunction2 : Symbol(StepFunction2, Decl(intraExpressionInferencesInContextSensitive1.ts, 50, 4)) ->TSchema : Symbol(TSchema, Decl(intraExpressionInferencesInContextSensitive1.ts, 57, 15)) - -): StepFunction2 { ->StepFunction2 : Symbol(StepFunction2, Decl(intraExpressionInferencesInContextSensitive1.ts, 50, 4)) ->TSchema : Symbol(TSchema, Decl(intraExpressionInferencesInContextSensitive1.ts, 57, 15)) +>StepFunction : Symbol(StepFunction, Decl(intraExpressionInferencesInContextSensitive1.ts, 14, 38)) +>TSchema : Symbol(TSchema, Decl(intraExpressionInferencesInContextSensitive1.ts, 21, 14)) return stepVal; ->stepVal : Symbol(stepVal, Decl(intraExpressionInferencesInContextSensitive1.ts, 57, 48)) +>stepVal : Symbol(stepVal, Decl(intraExpressionInferencesInContextSensitive1.ts, 21, 47)) } -const stepResult2 = step2((_something) => ({ ->stepResult2 : Symbol(stepResult2, Decl(intraExpressionInferencesInContextSensitive1.ts, 63, 5)) ->step2 : Symbol(step2, Decl(intraExpressionInferencesInContextSensitive1.ts, 55, 2)) ->_something : Symbol(_something, Decl(intraExpressionInferencesInContextSensitive1.ts, 63, 27)) +const stepResult = step((_something) => ({ +>stepResult : Symbol(stepResult, Decl(intraExpressionInferencesInContextSensitive1.ts, 27, 5)) +>step : Symbol(step, Decl(intraExpressionInferencesInContextSensitive1.ts, 19, 2)) +>_something : Symbol(_something, Decl(intraExpressionInferencesInContextSensitive1.ts, 27, 25)) schema: (thing) => ({ ->schema : Symbol(schema, Decl(intraExpressionInferencesInContextSensitive1.ts, 63, 44)) ->thing : Symbol(thing, Decl(intraExpressionInferencesInContextSensitive1.ts, 64, 11)) +>schema : Symbol(schema, Decl(intraExpressionInferencesInContextSensitive1.ts, 27, 42)) +>thing : Symbol(thing, Decl(intraExpressionInferencesInContextSensitive1.ts, 28, 11)) attribute: "anything", ->attribute : Symbol(attribute, Decl(intraExpressionInferencesInContextSensitive1.ts, 64, 23)) +>attribute : Symbol(attribute, Decl(intraExpressionInferencesInContextSensitive1.ts, 28, 23)) }), toAnswers: (keys) => { ->toAnswers : Symbol(toAnswers, Decl(intraExpressionInferencesInContextSensitive1.ts, 66, 5)) ->keys : Symbol(keys, Decl(intraExpressionInferencesInContextSensitive1.ts, 67, 14)) +>toAnswers : Symbol(toAnswers, Decl(intraExpressionInferencesInContextSensitive1.ts, 30, 5)) +>keys : Symbol(keys, Decl(intraExpressionInferencesInContextSensitive1.ts, 31, 14)) type Test = string extends typeof keys ? never : "true"; ->Test : Symbol(Test, Decl(intraExpressionInferencesInContextSensitive1.ts, 67, 24)) ->keys : Symbol(keys, Decl(intraExpressionInferencesInContextSensitive1.ts, 67, 14)) +>Test : Symbol(Test, Decl(intraExpressionInferencesInContextSensitive1.ts, 31, 24)) +>keys : Symbol(keys, Decl(intraExpressionInferencesInContextSensitive1.ts, 31, 14)) const test: Test = "true"; // ok ->test : Symbol(test, Decl(intraExpressionInferencesInContextSensitive1.ts, 69, 9)) ->Test : Symbol(Test, Decl(intraExpressionInferencesInContextSensitive1.ts, 67, 24)) +>test : Symbol(test, Decl(intraExpressionInferencesInContextSensitive1.ts, 33, 9)) +>Test : Symbol(Test, Decl(intraExpressionInferencesInContextSensitive1.ts, 31, 24)) return { test }; ->test : Symbol(test, Decl(intraExpressionInferencesInContextSensitive1.ts, 70, 12)) +>test : Symbol(test, Decl(intraExpressionInferencesInContextSensitive1.ts, 34, 12)) }, })); diff --git a/tests/baselines/reference/intraExpressionInferencesInContextSensitive1.types b/tests/baselines/reference/intraExpressionInferencesInContextSensitive1.types index deae7c6324933..1903b5f3f8593 100644 --- a/tests/baselines/reference/intraExpressionInferencesInContextSensitive1.types +++ b/tests/baselines/reference/intraExpressionInferencesInContextSensitive1.types @@ -1,15 +1,15 @@ //// [tests/cases/conformance/types/typeRelationships/typeInference/intraExpressionInferencesInContextSensitive1.ts] //// === intraExpressionInferencesInContextSensitive1.ts === -// https://github.com/microsoft/TypeScript/issues/60720 - type Options = { >Options : Options > : ^^^^^^^^^^^^^^^^^ - onStart?: () => TContext; ->onStart : (() => TContext) | undefined -> : ^^^^^^^ ^^^^^^^^^^^^^ + onStart?: (arg: number) => TContext; +>onStart : ((arg: number) => TContext) | undefined +> : ^^ ^^ ^^^^^ ^^^^^^^^^^^^^ +>arg : number +> : ^^^^^^ onEnd?: (context: TContext) => void; >onEnd : ((context: TContext) => void) | undefined @@ -36,103 +36,27 @@ function create(builder: (arg: boolean) => Options) { > : ^^^^ } -create((arg: boolean) => ({ ->create((arg: boolean) => ({ onStart: () => ({ time: new Date() }), onEnd: (context) => {},})) : Options<{ time: Date; }> -> : ^^^^^^^^^^^^^^^^^^^^^^^^ ->create : (builder: (arg: boolean) => Options) => Options -> : ^ ^^ ^^ ^^^^^^^^^^^^^^^^^^^^^^ ->(arg: boolean) => ({ onStart: () => ({ time: new Date() }), onEnd: (context) => {},}) : (arg: boolean) => { onStart: () => { time: Date; }; onEnd: (context: { time: Date; }) => void; } -> : ^ ^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ->arg : boolean -> : ^^^^^^^ ->({ onStart: () => ({ time: new Date() }), onEnd: (context) => {},}) : { onStart: () => { time: Date; }; onEnd: (context: { time: Date; }) => void; } -> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ->{ onStart: () => ({ time: new Date() }), onEnd: (context) => {},} : { onStart: () => { time: Date; }; onEnd: (context: { time: Date; }) => void; } -> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - - onStart: () => ({ time: new Date() }), ->onStart : () => { time: Date; } -> : ^^^^^^^^^^^^^^^^^^^^^ ->() => ({ time: new Date() }) : () => { time: Date; } -> : ^^^^^^^^^^^^^^^^^^^^^ ->({ time: new Date() }) : { time: Date; } -> : ^^^^^^^^^^^^^^^ ->{ time: new Date() } : { time: Date; } -> : ^^^^^^^^^^^^^^^ ->time : Date -> : ^^^^ ->new Date() : Date -> : ^^^^ ->Date : DateConstructor -> : ^^^^^^^^^^^^^^^ - - onEnd: (context) => {}, ->onEnd : (context: { time: Date; }) => void -> : ^ ^^^^^^^^^^^^^^^^^^^^^^^^^^ ->(context) => {} : (context: { time: Date; }) => void -> : ^ ^^^^^^^^^^^^^^^^^^^^^^^^^^ ->context : { time: Date; } -> : ^^^^^^^^^^^^^^^ - -})); - -create(() => ({ ->create(() => ({ onStart: () => ({ time: new Date() }), onEnd: (context) => {},})) : Options<{ time: Date; }> -> : ^^^^^^^^^^^^^^^^^^^^^^^^ ->create : (builder: (arg: boolean) => Options) => Options -> : ^ ^^ ^^ ^^^^^^^^^^^^^^^^^^^^^^ ->() => ({ onStart: () => ({ time: new Date() }), onEnd: (context) => {},}) : () => { onStart: () => { time: Date; }; onEnd: (context: { time: Date; }) => void; } -> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ->({ onStart: () => ({ time: new Date() }), onEnd: (context) => {},}) : { onStart: () => { time: Date; }; onEnd: (context: { time: Date; }) => void; } -> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ->{ onStart: () => ({ time: new Date() }), onEnd: (context) => {},} : { onStart: () => { time: Date; }; onEnd: (context: { time: Date; }) => void; } -> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - - onStart: () => ({ time: new Date() }), ->onStart : () => { time: Date; } -> : ^^^^^^^^^^^^^^^^^^^^^ ->() => ({ time: new Date() }) : () => { time: Date; } -> : ^^^^^^^^^^^^^^^^^^^^^ ->({ time: new Date() }) : { time: Date; } -> : ^^^^^^^^^^^^^^^ ->{ time: new Date() } : { time: Date; } -> : ^^^^^^^^^^^^^^^ ->time : Date -> : ^^^^ ->new Date() : Date -> : ^^^^ ->Date : DateConstructor -> : ^^^^^^^^^^^^^^^ - - onEnd: (context) => {}, ->onEnd : (context: { time: Date; }) => void -> : ^ ^^^^^^^^^^^^^^^^^^^^^^^^^^ ->(context) => {} : (context: { time: Date; }) => void -> : ^ ^^^^^^^^^^^^^^^^^^^^^^^^^^ ->context : { time: Date; } -> : ^^^^^^^^^^^^^^^ - -})); - create((arg) => ({ ->create((arg) => ({ onStart: () => ({ time: new Date() }), onEnd: (context) => {},})) : Options<{ time: Date; }> -> : ^^^^^^^^^^^^^^^^^^^^^^^^ +>create((arg) => ({ onStart: (arg) => ({ time: new Date() }), onEnd: (context) => {},})) : Options<{ time: Date; }> +> : ^^^^^^^^^^^^^^^^^^^^^^^^ >create : (builder: (arg: boolean) => Options) => Options > : ^ ^^ ^^ ^^^^^^^^^^^^^^^^^^^^^^ ->(arg) => ({ onStart: () => ({ time: new Date() }), onEnd: (context) => {},}) : (arg: boolean) => { onStart: () => { time: Date; }; onEnd: (context: { time: Date; }) => void; } -> : ^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +>(arg) => ({ onStart: (arg) => ({ time: new Date() }), onEnd: (context) => {},}) : (arg: boolean) => { onStart: (arg: number) => { time: Date; }; onEnd: (context: { time: Date; }) => void; } +> : ^ ^^^^^^^^^^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ >arg : boolean > : ^^^^^^^ ->({ onStart: () => ({ time: new Date() }), onEnd: (context) => {},}) : { onStart: () => { time: Date; }; onEnd: (context: { time: Date; }) => void; } -> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ->{ onStart: () => ({ time: new Date() }), onEnd: (context) => {},} : { onStart: () => { time: Date; }; onEnd: (context: { time: Date; }) => void; } -> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - - onStart: () => ({ time: new Date() }), ->onStart : () => { time: Date; } -> : ^^^^^^^^^^^^^^^^^^^^^ ->() => ({ time: new Date() }) : () => { time: Date; } -> : ^^^^^^^^^^^^^^^^^^^^^ +>({ onStart: (arg) => ({ time: new Date() }), onEnd: (context) => {},}) : { onStart: (arg: number) => { time: Date; }; onEnd: (context: { time: Date; }) => void; } +> : ^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +>{ onStart: (arg) => ({ time: new Date() }), onEnd: (context) => {},} : { onStart: (arg: number) => { time: Date; }; onEnd: (context: { time: Date; }) => void; } +> : ^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + + onStart: (arg) => ({ time: new Date() }), +>onStart : (arg: number) => { time: Date; } +> : ^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +>(arg) => ({ time: new Date() }) : (arg: number) => { time: Date; } +> : ^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +>arg : number +> : ^^^^^^ >({ time: new Date() }) : { time: Date; } > : ^^^^^^^^^^^^^^^ >{ time: new Date() } : { time: Date; } @@ -154,8 +78,6 @@ create((arg) => ({ })); -// https://github.com/microsoft/TypeScript/issues/57021 - type Schema = Record; >Schema : Schema > : ^^^^^^ @@ -166,9 +88,11 @@ type StepFunction = (anything: unknown) => { >anything : unknown > : ^^^^^^^ - readonly schema: TSchema; ->schema : TSchema -> : ^^^^^^^ + readonly schema: (thing: number) => TSchema; +>schema : (thing: number) => TSchema +> : ^ ^^ ^^^^^ +>thing : number +> : ^^^^^^ readonly toAnswers?: (keys: keyof TSchema) => unknown; >toAnswers : ((keys: keyof TSchema) => unknown) | undefined @@ -178,9 +102,9 @@ type StepFunction = (anything: unknown) => { }; -function step1( ->step1 : (stepVal: StepFunction) => StepFunction -> : ^ ^^^^^^^^^ ^^^^^^^^^^^ ^^ ^^^^^ +function step( +>step : (stepVal: StepFunction) => StepFunction +> : ^ ^^^^^^^^^ ^^^^^^^^^^^ ^^ ^^^^^ stepVal: StepFunction, >stepVal : StepFunction @@ -192,105 +116,13 @@ function step1( > : ^^^^^^^^^^^^^^^^^^^^^ } -const stepResult1 = step1((_something) => ({ ->stepResult1 : StepFunction<{ attribute: string; }> -> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ->step1((_something) => ({ schema: { attribute: "anything", }, toAnswers: (keys) => { type Test = string extends typeof keys ? never : "true"; const test: Test = "true"; // ok return { test }; },})) : StepFunction<{ attribute: string; }> -> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ->step1 : (stepVal: StepFunction) => StepFunction -> : ^ ^^^^^^^^^ ^^^^^^^^^^^ ^^ ^^^^^ ->(_something) => ({ schema: { attribute: "anything", }, toAnswers: (keys) => { type Test = string extends typeof keys ? never : "true"; const test: Test = "true"; // ok return { test }; },}) : (_something: unknown) => { schema: { attribute: string; }; toAnswers: (keys: "attribute") => { test: "true"; }; } -> : ^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ->_something : unknown -> : ^^^^^^^ ->({ schema: { attribute: "anything", }, toAnswers: (keys) => { type Test = string extends typeof keys ? never : "true"; const test: Test = "true"; // ok return { test }; },}) : { schema: { attribute: string; }; toAnswers: (keys: "attribute") => { test: "true"; }; } -> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ->{ schema: { attribute: "anything", }, toAnswers: (keys) => { type Test = string extends typeof keys ? never : "true"; const test: Test = "true"; // ok return { test }; },} : { schema: { attribute: string; }; toAnswers: (keys: "attribute") => { test: "true"; }; } -> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - - schema: { ->schema : { attribute: string; } -> : ^^^^^^^^^^^^^^^^^^^^^^ ->{ attribute: "anything", } : { attribute: string; } -> : ^^^^^^^^^^^^^^^^^^^^^^ - - attribute: "anything", ->attribute : string -> : ^^^^^^ ->"anything" : "anything" -> : ^^^^^^^^^^ - - }, - toAnswers: (keys) => { ->toAnswers : (keys: "attribute") => { test: "true"; } -> : ^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ->(keys) => { type Test = string extends typeof keys ? never : "true"; const test: Test = "true"; // ok return { test }; } : (keys: "attribute") => { test: "true"; } -> : ^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ->keys : "attribute" -> : ^^^^^^^^^^^ - - type Test = string extends typeof keys ? never : "true"; ->Test : "true" -> : ^^^^^^ ->keys : "attribute" -> : ^^^^^^^^^^^ - - const test: Test = "true"; // ok ->test : "true" -> : ^^^^^^ ->"true" : "true" -> : ^^^^^^ - - return { test }; ->{ test } : { test: "true"; } -> : ^^^^^^^^^^^^^^^^^ ->test : "true" -> : ^^^^^^ - - }, -})); - -type StepFunction2 = (anything: unknown) => { ->StepFunction2 : StepFunction2 -> : ^^^^^^^^^^^^^^^^^^^^^^ ->anything : unknown -> : ^^^^^^^ - - readonly schema: (thing: number) => TSchema; ->schema : (thing: number) => TSchema -> : ^ ^^ ^^^^^ ->thing : number -> : ^^^^^^ - - readonly toAnswers?: (keys: keyof TSchema) => unknown; ->toAnswers : ((keys: keyof TSchema) => unknown) | undefined -> : ^^ ^^ ^^^^^ ^^^^^^^^^^^^^ ->keys : keyof TSchema -> : ^^^^^^^^^^^^^ - -}; - -function step2( ->step2 : (stepVal: StepFunction2) => StepFunction2 -> : ^ ^^^^^^^^^ ^^^^^^^^^^^ ^^ ^^^^^ - - stepVal: StepFunction2, ->stepVal : StepFunction2 -> : ^^^^^^^^^^^^^^^^^^^^^^ - -): StepFunction2 { - return stepVal; ->stepVal : StepFunction2 -> : ^^^^^^^^^^^^^^^^^^^^^^ -} - -const stepResult2 = step2((_something) => ({ ->stepResult2 : StepFunction2<{ attribute: string; }> -> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ->step2((_something) => ({ schema: (thing) => ({ attribute: "anything", }), toAnswers: (keys) => { type Test = string extends typeof keys ? never : "true"; const test: Test = "true"; // ok return { test }; },})) : StepFunction2<{ attribute: string; }> -> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ->step2 : (stepVal: StepFunction2) => StepFunction2 -> : ^ ^^^^^^^^^ ^^^^^^^^^^^ ^^ ^^^^^ +const stepResult = step((_something) => ({ +>stepResult : StepFunction<{ attribute: string; }> +> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +>step((_something) => ({ schema: (thing) => ({ attribute: "anything", }), toAnswers: (keys) => { type Test = string extends typeof keys ? never : "true"; const test: Test = "true"; // ok return { test }; },})) : StepFunction<{ attribute: string; }> +> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +>step : (stepVal: StepFunction) => StepFunction +> : ^ ^^^^^^^^^ ^^^^^^^^^^^ ^^ ^^^^^ >(_something) => ({ schema: (thing) => ({ attribute: "anything", }), toAnswers: (keys) => { type Test = string extends typeof keys ? never : "true"; const test: Test = "true"; // ok return { test }; },}) : (_something: unknown) => { schema: (thing: number) => { attribute: string; }; toAnswers: (keys: "attribute") => { test: "true"; }; } > : ^ ^^^^^^^^^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ >_something : unknown diff --git a/tests/cases/conformance/types/typeRelationships/typeInference/InferFromReturnsInContextSensitive1.ts b/tests/cases/conformance/types/typeRelationships/typeInference/InferFromReturnsInContextSensitive1.ts new file mode 100644 index 0000000000000..0a76276f58b4f --- /dev/null +++ b/tests/cases/conformance/types/typeRelationships/typeInference/InferFromReturnsInContextSensitive1.ts @@ -0,0 +1,44 @@ +// @strict: true +// @declaration: true + +// https://github.com/microsoft/TypeScript/issues/60720 + +type Options = { + onStart?: () => TContext; + onEnd?: (context: TContext) => void; +}; + +function create(builder: (arg: boolean) => Options) { + return builder(true); +} + +create((arg) => ({ + onStart: () => ({ time: new Date() }), + onEnd: (context) => {}, +})); + +// https://github.com/microsoft/TypeScript/issues/57021 + +type Schema = Record; + +type StepFunction = (anything: unknown) => { + readonly schema: TSchema; + readonly toAnswers?: (keys: keyof TSchema) => unknown; +}; + +function step1( + stepVal: StepFunction, +): StepFunction { + return stepVal; +} + +const stepResult1 = step1((_something) => ({ + schema: { + attribute: "anything", + }, + toAnswers: (keys) => { + type Test = string extends typeof keys ? never : "true"; + const test: Test = "true"; // ok + return { test }; + }, +})); diff --git a/tests/cases/conformance/types/typeRelationships/typeInference/intraExpressionInferencesInContextSensitive1.ts b/tests/cases/conformance/types/typeRelationships/typeInference/intraExpressionInferencesInContextSensitive1.ts index e8de5fcbcafe6..927d7fd989499 100644 --- a/tests/cases/conformance/types/typeRelationships/typeInference/intraExpressionInferencesInContextSensitive1.ts +++ b/tests/cases/conformance/types/typeRelationships/typeInference/intraExpressionInferencesInContextSensitive1.ts @@ -1,10 +1,8 @@ // @strict: true // @declaration: true -// https://github.com/microsoft/TypeScript/issues/60720 - type Options = { - onStart?: () => TContext; + onStart?: (arg: number) => TContext; onEnd?: (context: TContext) => void; }; @@ -12,59 +10,25 @@ function create(builder: (arg: boolean) => Options) { return builder(true); } -create((arg: boolean) => ({ - onStart: () => ({ time: new Date() }), - onEnd: (context) => {}, -})); - -create(() => ({ - onStart: () => ({ time: new Date() }), - onEnd: (context) => {}, -})); - create((arg) => ({ - onStart: () => ({ time: new Date() }), + onStart: (arg) => ({ time: new Date() }), onEnd: (context) => {}, })); -// https://github.com/microsoft/TypeScript/issues/57021 - type Schema = Record; type StepFunction = (anything: unknown) => { - readonly schema: TSchema; + readonly schema: (thing: number) => TSchema; readonly toAnswers?: (keys: keyof TSchema) => unknown; }; -function step1( +function step( stepVal: StepFunction, ): StepFunction { return stepVal; } -const stepResult1 = step1((_something) => ({ - schema: { - attribute: "anything", - }, - toAnswers: (keys) => { - type Test = string extends typeof keys ? never : "true"; - const test: Test = "true"; // ok - return { test }; - }, -})); - -type StepFunction2 = (anything: unknown) => { - readonly schema: (thing: number) => TSchema; - readonly toAnswers?: (keys: keyof TSchema) => unknown; -}; - -function step2( - stepVal: StepFunction2, -): StepFunction2 { - return stepVal; -} - -const stepResult2 = step2((_something) => ({ +const stepResult = step((_something) => ({ schema: (thing) => ({ attribute: "anything", }), From 23c6c33dc7ee0a7ef5eea6cc7b9d0e28926584f9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mateusz=20Burzy=C5=84ski?= Date: Mon, 6 Jan 2025 10:14:49 +0100 Subject: [PATCH 8/8] add more tests --- .../InferFromReturnsInContextSensitive1.js | 220 ++++++- ...nferFromReturnsInContextSensitive1.symbols | 346 ++++++++-- .../InferFromReturnsInContextSensitive1.types | 591 +++++++++++++++++- ...ExpressionInferencesInContextSensitive1.js | 58 ++ ...ssionInferencesInContextSensitive1.symbols | 95 +++ ...ressionInferencesInContextSensitive1.types | 171 +++++ .../InferFromReturnsInContextSensitive1.ts | 110 +++- ...ExpressionInferencesInContextSensitive1.ts | 30 + 8 files changed, 1571 insertions(+), 50 deletions(-) diff --git a/tests/baselines/reference/InferFromReturnsInContextSensitive1.js b/tests/baselines/reference/InferFromReturnsInContextSensitive1.js index f62ce1e4fdcbe..177dc45641039 100644 --- a/tests/baselines/reference/InferFromReturnsInContextSensitive1.js +++ b/tests/baselines/reference/InferFromReturnsInContextSensitive1.js @@ -17,6 +17,11 @@ create((arg) => ({ onEnd: (context) => {}, })); +create((arg) => ({ + onEnd: (context) => {}, + onStart: () => ({ time: new Date() }), +})); + // https://github.com/microsoft/TypeScript/issues/57021 type Schema = Record; @@ -26,13 +31,13 @@ type StepFunction = (anything: unknown) => { readonly toAnswers?: (keys: keyof TSchema) => unknown; }; -function step1( +function step( stepVal: StepFunction, ): StepFunction { return stepVal; } -const stepResult1 = step1((_something) => ({ +const stepResult1 = step((_something) => ({ schema: { attribute: "anything", }, @@ -42,6 +47,107 @@ const stepResult1 = step1((_something) => ({ return { test }; }, })); + +const stepResult2 = step((_something) => ({ + toAnswers: (keys) => { + type Test = string extends typeof keys ? never : "true"; + const test: Test = "true"; // ok + return { test }; + }, + schema: { + attribute: "anything", + }, +})); + +type Fn1 = (anything: unknown) => { + stuff: T; + consume: (arg: T) => (anything: unknown) => { + stuff2: T2; + consume2: (arg: T2) => void; + }; +}; + +declare function test1(fn: Fn1): [T, T2]; + +const res1 = test1((_something) => ({ + stuff: "foo", + consume: (arg) => { + return (_something) => ({ + stuff2: 42, + consume2: (arg2) => {}, + }); + }, +})); + +const res2 = test1((_something) => ({ + consume: (arg) => { + return (_something) => ({ + consume2: (arg2) => {}, + stuff2: 42, + }); + }, + stuff: "foo", +})); + +const res3 = test1((_something) => ({ + stuff: "foo", + consume: () => { + return (_something) => ({ + stuff2: 42, + consume2: (arg2) => {}, + }); + }, +})); + +const res4 = test1((_something) => ({ + consume: () => { + return (_something) => ({ + consume2: (arg2) => {}, + stuff2: 42, + }); + }, + stuff: "foo", +})); + +const res5 = test1((_something) => ({ + stuff: "foo", + consume: () => { + return () => ({ + stuff2: 42, + consume2: (arg2) => {}, + }); + }, +})); + +const res6 = test1((_something) => ({ + consume: () => { + return () => ({ + consume2: (arg2) => {}, + stuff2: 42, + }); + }, + stuff: "foo", +})); + +const res7 = test1((_something) => ({ + stuff: "foo", + consume: () => { + return () => ({ + stuff2: 42, + consume2: () => {}, + }); + }, +})); + +const res8 = test1((_something) => ({ + consume: () => { + return () => ({ + consume2: () => {}, + stuff2: 42, + }); + }, + stuff: "foo", +})); //// [InferFromReturnsInContextSensitive1.js] @@ -54,10 +160,14 @@ create(function (arg) { return ({ onStart: function () { return ({ time: new Date() }); }, onEnd: function (context) { }, }); }); -function step1(stepVal) { +create(function (arg) { return ({ + onEnd: function (context) { }, + onStart: function () { return ({ time: new Date() }); }, +}); }); +function step(stepVal) { return stepVal; } -var stepResult1 = step1(function (_something) { return ({ +var stepResult1 = step(function (_something) { return ({ schema: { attribute: "anything", }, @@ -66,6 +176,87 @@ var stepResult1 = step1(function (_something) { return ({ return { test: test }; }, }); }); +var stepResult2 = step(function (_something) { return ({ + toAnswers: function (keys) { + var test = "true"; // ok + return { test: test }; + }, + schema: { + attribute: "anything", + }, +}); }); +var res1 = test1(function (_something) { return ({ + stuff: "foo", + consume: function (arg) { + return function (_something) { return ({ + stuff2: 42, + consume2: function (arg2) { }, + }); }; + }, +}); }); +var res2 = test1(function (_something) { return ({ + consume: function (arg) { + return function (_something) { return ({ + consume2: function (arg2) { }, + stuff2: 42, + }); }; + }, + stuff: "foo", +}); }); +var res3 = test1(function (_something) { return ({ + stuff: "foo", + consume: function () { + return function (_something) { return ({ + stuff2: 42, + consume2: function (arg2) { }, + }); }; + }, +}); }); +var res4 = test1(function (_something) { return ({ + consume: function () { + return function (_something) { return ({ + consume2: function (arg2) { }, + stuff2: 42, + }); }; + }, + stuff: "foo", +}); }); +var res5 = test1(function (_something) { return ({ + stuff: "foo", + consume: function () { + return function () { return ({ + stuff2: 42, + consume2: function (arg2) { }, + }); }; + }, +}); }); +var res6 = test1(function (_something) { return ({ + consume: function () { + return function () { return ({ + consume2: function (arg2) { }, + stuff2: 42, + }); }; + }, + stuff: "foo", +}); }); +var res7 = test1(function (_something) { return ({ + stuff: "foo", + consume: function () { + return function () { return ({ + stuff2: 42, + consume2: function () { }, + }); }; + }, +}); }); +var res8 = test1(function (_something) { return ({ + consume: function () { + return function () { return ({ + consume2: function () { }, + stuff2: 42, + }); }; + }, + stuff: "foo", +}); }); //// [InferFromReturnsInContextSensitive1.d.ts] @@ -79,7 +270,26 @@ type StepFunction = (anything: unknown) => { readonly schema: TSchema; readonly toAnswers?: (keys: keyof TSchema) => unknown; }; -declare function step1(stepVal: StepFunction): StepFunction; +declare function step(stepVal: StepFunction): StepFunction; declare const stepResult1: StepFunction<{ attribute: string; }>; +declare const stepResult2: StepFunction<{ + attribute: string; +}>; +type Fn1 = (anything: unknown) => { + stuff: T; + consume: (arg: T) => (anything: unknown) => { + stuff2: T2; + consume2: (arg: T2) => void; + }; +}; +declare function test1(fn: Fn1): [T, T2]; +declare const res1: [string, number]; +declare const res2: [string, number]; +declare const res3: [string, number]; +declare const res4: [string, number]; +declare const res5: [string, number]; +declare const res6: [string, number]; +declare const res7: [string, number]; +declare const res8: [string, number]; diff --git a/tests/baselines/reference/InferFromReturnsInContextSensitive1.symbols b/tests/baselines/reference/InferFromReturnsInContextSensitive1.symbols index 0ed0951e1caf6..2b87289576f5b 100644 --- a/tests/baselines/reference/InferFromReturnsInContextSensitive1.symbols +++ b/tests/baselines/reference/InferFromReturnsInContextSensitive1.symbols @@ -45,76 +45,352 @@ create((arg) => ({ })); +create((arg) => ({ +>create : Symbol(create, Decl(InferFromReturnsInContextSensitive1.ts, 5, 2)) +>arg : Symbol(arg, Decl(InferFromReturnsInContextSensitive1.ts, 16, 8)) + + onEnd: (context) => {}, +>onEnd : Symbol(onEnd, Decl(InferFromReturnsInContextSensitive1.ts, 16, 18)) +>context : Symbol(context, Decl(InferFromReturnsInContextSensitive1.ts, 17, 10)) + + onStart: () => ({ time: new Date() }), +>onStart : Symbol(onStart, Decl(InferFromReturnsInContextSensitive1.ts, 17, 25)) +>time : Symbol(time, Decl(InferFromReturnsInContextSensitive1.ts, 18, 19)) +>Date : Symbol(Date, Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --), Decl(lib.scripthost.d.ts, --, --)) + +})); + // https://github.com/microsoft/TypeScript/issues/57021 type Schema = Record; ->Schema : Symbol(Schema, Decl(InferFromReturnsInContextSensitive1.ts, 14, 4)) +>Schema : Symbol(Schema, Decl(InferFromReturnsInContextSensitive1.ts, 19, 4)) >Record : Symbol(Record, Decl(lib.es5.d.ts, --, --)) type StepFunction = (anything: unknown) => { ->StepFunction : Symbol(StepFunction, Decl(InferFromReturnsInContextSensitive1.ts, 18, 38)) ->TSchema : Symbol(TSchema, Decl(InferFromReturnsInContextSensitive1.ts, 20, 18)) ->Schema : Symbol(Schema, Decl(InferFromReturnsInContextSensitive1.ts, 14, 4)) ->Schema : Symbol(Schema, Decl(InferFromReturnsInContextSensitive1.ts, 14, 4)) ->anything : Symbol(anything, Decl(InferFromReturnsInContextSensitive1.ts, 20, 54)) +>StepFunction : Symbol(StepFunction, Decl(InferFromReturnsInContextSensitive1.ts, 23, 38)) +>TSchema : Symbol(TSchema, Decl(InferFromReturnsInContextSensitive1.ts, 25, 18)) +>Schema : Symbol(Schema, Decl(InferFromReturnsInContextSensitive1.ts, 19, 4)) +>Schema : Symbol(Schema, Decl(InferFromReturnsInContextSensitive1.ts, 19, 4)) +>anything : Symbol(anything, Decl(InferFromReturnsInContextSensitive1.ts, 25, 54)) readonly schema: TSchema; ->schema : Symbol(schema, Decl(InferFromReturnsInContextSensitive1.ts, 20, 77)) ->TSchema : Symbol(TSchema, Decl(InferFromReturnsInContextSensitive1.ts, 20, 18)) +>schema : Symbol(schema, Decl(InferFromReturnsInContextSensitive1.ts, 25, 77)) +>TSchema : Symbol(TSchema, Decl(InferFromReturnsInContextSensitive1.ts, 25, 18)) readonly toAnswers?: (keys: keyof TSchema) => unknown; ->toAnswers : Symbol(toAnswers, Decl(InferFromReturnsInContextSensitive1.ts, 21, 27)) ->keys : Symbol(keys, Decl(InferFromReturnsInContextSensitive1.ts, 22, 24)) ->TSchema : Symbol(TSchema, Decl(InferFromReturnsInContextSensitive1.ts, 20, 18)) +>toAnswers : Symbol(toAnswers, Decl(InferFromReturnsInContextSensitive1.ts, 26, 27)) +>keys : Symbol(keys, Decl(InferFromReturnsInContextSensitive1.ts, 27, 24)) +>TSchema : Symbol(TSchema, Decl(InferFromReturnsInContextSensitive1.ts, 25, 18)) }; -function step1( ->step1 : Symbol(step1, Decl(InferFromReturnsInContextSensitive1.ts, 23, 2)) ->TSchema : Symbol(TSchema, Decl(InferFromReturnsInContextSensitive1.ts, 25, 15)) ->Schema : Symbol(Schema, Decl(InferFromReturnsInContextSensitive1.ts, 14, 4)) ->Schema : Symbol(Schema, Decl(InferFromReturnsInContextSensitive1.ts, 14, 4)) +function step( +>step : Symbol(step, Decl(InferFromReturnsInContextSensitive1.ts, 28, 2)) +>TSchema : Symbol(TSchema, Decl(InferFromReturnsInContextSensitive1.ts, 30, 14)) +>Schema : Symbol(Schema, Decl(InferFromReturnsInContextSensitive1.ts, 19, 4)) +>Schema : Symbol(Schema, Decl(InferFromReturnsInContextSensitive1.ts, 19, 4)) stepVal: StepFunction, ->stepVal : Symbol(stepVal, Decl(InferFromReturnsInContextSensitive1.ts, 25, 48)) ->StepFunction : Symbol(StepFunction, Decl(InferFromReturnsInContextSensitive1.ts, 18, 38)) ->TSchema : Symbol(TSchema, Decl(InferFromReturnsInContextSensitive1.ts, 25, 15)) +>stepVal : Symbol(stepVal, Decl(InferFromReturnsInContextSensitive1.ts, 30, 47)) +>StepFunction : Symbol(StepFunction, Decl(InferFromReturnsInContextSensitive1.ts, 23, 38)) +>TSchema : Symbol(TSchema, Decl(InferFromReturnsInContextSensitive1.ts, 30, 14)) ): StepFunction { ->StepFunction : Symbol(StepFunction, Decl(InferFromReturnsInContextSensitive1.ts, 18, 38)) ->TSchema : Symbol(TSchema, Decl(InferFromReturnsInContextSensitive1.ts, 25, 15)) +>StepFunction : Symbol(StepFunction, Decl(InferFromReturnsInContextSensitive1.ts, 23, 38)) +>TSchema : Symbol(TSchema, Decl(InferFromReturnsInContextSensitive1.ts, 30, 14)) return stepVal; ->stepVal : Symbol(stepVal, Decl(InferFromReturnsInContextSensitive1.ts, 25, 48)) +>stepVal : Symbol(stepVal, Decl(InferFromReturnsInContextSensitive1.ts, 30, 47)) } -const stepResult1 = step1((_something) => ({ ->stepResult1 : Symbol(stepResult1, Decl(InferFromReturnsInContextSensitive1.ts, 31, 5)) ->step1 : Symbol(step1, Decl(InferFromReturnsInContextSensitive1.ts, 23, 2)) ->_something : Symbol(_something, Decl(InferFromReturnsInContextSensitive1.ts, 31, 27)) +const stepResult1 = step((_something) => ({ +>stepResult1 : Symbol(stepResult1, Decl(InferFromReturnsInContextSensitive1.ts, 36, 5)) +>step : Symbol(step, Decl(InferFromReturnsInContextSensitive1.ts, 28, 2)) +>_something : Symbol(_something, Decl(InferFromReturnsInContextSensitive1.ts, 36, 26)) schema: { ->schema : Symbol(schema, Decl(InferFromReturnsInContextSensitive1.ts, 31, 44)) +>schema : Symbol(schema, Decl(InferFromReturnsInContextSensitive1.ts, 36, 43)) attribute: "anything", ->attribute : Symbol(attribute, Decl(InferFromReturnsInContextSensitive1.ts, 32, 11)) +>attribute : Symbol(attribute, Decl(InferFromReturnsInContextSensitive1.ts, 37, 11)) + + }, + toAnswers: (keys) => { +>toAnswers : Symbol(toAnswers, Decl(InferFromReturnsInContextSensitive1.ts, 39, 4)) +>keys : Symbol(keys, Decl(InferFromReturnsInContextSensitive1.ts, 40, 14)) + + type Test = string extends typeof keys ? never : "true"; +>Test : Symbol(Test, Decl(InferFromReturnsInContextSensitive1.ts, 40, 24)) +>keys : Symbol(keys, Decl(InferFromReturnsInContextSensitive1.ts, 40, 14)) + + const test: Test = "true"; // ok +>test : Symbol(test, Decl(InferFromReturnsInContextSensitive1.ts, 42, 9)) +>Test : Symbol(Test, Decl(InferFromReturnsInContextSensitive1.ts, 40, 24)) + + return { test }; +>test : Symbol(test, Decl(InferFromReturnsInContextSensitive1.ts, 43, 12)) }, +})); + +const stepResult2 = step((_something) => ({ +>stepResult2 : Symbol(stepResult2, Decl(InferFromReturnsInContextSensitive1.ts, 47, 5)) +>step : Symbol(step, Decl(InferFromReturnsInContextSensitive1.ts, 28, 2)) +>_something : Symbol(_something, Decl(InferFromReturnsInContextSensitive1.ts, 47, 26)) + toAnswers: (keys) => { ->toAnswers : Symbol(toAnswers, Decl(InferFromReturnsInContextSensitive1.ts, 34, 4)) ->keys : Symbol(keys, Decl(InferFromReturnsInContextSensitive1.ts, 35, 14)) +>toAnswers : Symbol(toAnswers, Decl(InferFromReturnsInContextSensitive1.ts, 47, 43)) +>keys : Symbol(keys, Decl(InferFromReturnsInContextSensitive1.ts, 48, 14)) type Test = string extends typeof keys ? never : "true"; ->Test : Symbol(Test, Decl(InferFromReturnsInContextSensitive1.ts, 35, 24)) ->keys : Symbol(keys, Decl(InferFromReturnsInContextSensitive1.ts, 35, 14)) +>Test : Symbol(Test, Decl(InferFromReturnsInContextSensitive1.ts, 48, 24)) +>keys : Symbol(keys, Decl(InferFromReturnsInContextSensitive1.ts, 48, 14)) const test: Test = "true"; // ok ->test : Symbol(test, Decl(InferFromReturnsInContextSensitive1.ts, 37, 9)) ->Test : Symbol(Test, Decl(InferFromReturnsInContextSensitive1.ts, 35, 24)) +>test : Symbol(test, Decl(InferFromReturnsInContextSensitive1.ts, 50, 9)) +>Test : Symbol(Test, Decl(InferFromReturnsInContextSensitive1.ts, 48, 24)) return { test }; ->test : Symbol(test, Decl(InferFromReturnsInContextSensitive1.ts, 38, 12)) +>test : Symbol(test, Decl(InferFromReturnsInContextSensitive1.ts, 51, 12)) + + }, + schema: { +>schema : Symbol(schema, Decl(InferFromReturnsInContextSensitive1.ts, 52, 4)) + + attribute: "anything", +>attribute : Symbol(attribute, Decl(InferFromReturnsInContextSensitive1.ts, 53, 11)) + + }, +})); + +type Fn1 = (anything: unknown) => { +>Fn1 : Symbol(Fn1, Decl(InferFromReturnsInContextSensitive1.ts, 56, 4)) +>T : Symbol(T, Decl(InferFromReturnsInContextSensitive1.ts, 58, 9)) +>T2 : Symbol(T2, Decl(InferFromReturnsInContextSensitive1.ts, 58, 11)) +>anything : Symbol(anything, Decl(InferFromReturnsInContextSensitive1.ts, 58, 19)) + + stuff: T; +>stuff : Symbol(stuff, Decl(InferFromReturnsInContextSensitive1.ts, 58, 42)) +>T : Symbol(T, Decl(InferFromReturnsInContextSensitive1.ts, 58, 9)) + + consume: (arg: T) => (anything: unknown) => { +>consume : Symbol(consume, Decl(InferFromReturnsInContextSensitive1.ts, 59, 11)) +>arg : Symbol(arg, Decl(InferFromReturnsInContextSensitive1.ts, 60, 12)) +>T : Symbol(T, Decl(InferFromReturnsInContextSensitive1.ts, 58, 9)) +>anything : Symbol(anything, Decl(InferFromReturnsInContextSensitive1.ts, 60, 24)) + + stuff2: T2; +>stuff2 : Symbol(stuff2, Decl(InferFromReturnsInContextSensitive1.ts, 60, 47)) +>T2 : Symbol(T2, Decl(InferFromReturnsInContextSensitive1.ts, 58, 11)) + + consume2: (arg: T2) => void; +>consume2 : Symbol(consume2, Decl(InferFromReturnsInContextSensitive1.ts, 61, 15)) +>arg : Symbol(arg, Decl(InferFromReturnsInContextSensitive1.ts, 62, 15)) +>T2 : Symbol(T2, Decl(InferFromReturnsInContextSensitive1.ts, 58, 11)) + + }; +}; + +declare function test1(fn: Fn1): [T, T2]; +>test1 : Symbol(test1, Decl(InferFromReturnsInContextSensitive1.ts, 64, 2)) +>T : Symbol(T, Decl(InferFromReturnsInContextSensitive1.ts, 66, 23)) +>T2 : Symbol(T2, Decl(InferFromReturnsInContextSensitive1.ts, 66, 25)) +>fn : Symbol(fn, Decl(InferFromReturnsInContextSensitive1.ts, 66, 30)) +>Fn1 : Symbol(Fn1, Decl(InferFromReturnsInContextSensitive1.ts, 56, 4)) +>T : Symbol(T, Decl(InferFromReturnsInContextSensitive1.ts, 66, 23)) +>T2 : Symbol(T2, Decl(InferFromReturnsInContextSensitive1.ts, 66, 25)) +>T : Symbol(T, Decl(InferFromReturnsInContextSensitive1.ts, 66, 23)) +>T2 : Symbol(T2, Decl(InferFromReturnsInContextSensitive1.ts, 66, 25)) + +const res1 = test1((_something) => ({ +>res1 : Symbol(res1, Decl(InferFromReturnsInContextSensitive1.ts, 68, 5)) +>test1 : Symbol(test1, Decl(InferFromReturnsInContextSensitive1.ts, 64, 2)) +>_something : Symbol(_something, Decl(InferFromReturnsInContextSensitive1.ts, 68, 20)) + + stuff: "foo", +>stuff : Symbol(stuff, Decl(InferFromReturnsInContextSensitive1.ts, 68, 37)) + + consume: (arg) => { +>consume : Symbol(consume, Decl(InferFromReturnsInContextSensitive1.ts, 69, 15)) +>arg : Symbol(arg, Decl(InferFromReturnsInContextSensitive1.ts, 70, 12)) + + return (_something) => ({ +>_something : Symbol(_something, Decl(InferFromReturnsInContextSensitive1.ts, 71, 12)) + + stuff2: 42, +>stuff2 : Symbol(stuff2, Decl(InferFromReturnsInContextSensitive1.ts, 71, 29)) + + consume2: (arg2) => {}, +>consume2 : Symbol(consume2, Decl(InferFromReturnsInContextSensitive1.ts, 72, 17)) +>arg2 : Symbol(arg2, Decl(InferFromReturnsInContextSensitive1.ts, 73, 17)) + + }); + }, +})); + +const res2 = test1((_something) => ({ +>res2 : Symbol(res2, Decl(InferFromReturnsInContextSensitive1.ts, 78, 5)) +>test1 : Symbol(test1, Decl(InferFromReturnsInContextSensitive1.ts, 64, 2)) +>_something : Symbol(_something, Decl(InferFromReturnsInContextSensitive1.ts, 78, 20)) + + consume: (arg) => { +>consume : Symbol(consume, Decl(InferFromReturnsInContextSensitive1.ts, 78, 37)) +>arg : Symbol(arg, Decl(InferFromReturnsInContextSensitive1.ts, 79, 12)) + + return (_something) => ({ +>_something : Symbol(_something, Decl(InferFromReturnsInContextSensitive1.ts, 80, 12)) + + consume2: (arg2) => {}, +>consume2 : Symbol(consume2, Decl(InferFromReturnsInContextSensitive1.ts, 80, 29)) +>arg2 : Symbol(arg2, Decl(InferFromReturnsInContextSensitive1.ts, 81, 17)) + + stuff2: 42, +>stuff2 : Symbol(stuff2, Decl(InferFromReturnsInContextSensitive1.ts, 81, 29)) + }); }, + stuff: "foo", +>stuff : Symbol(stuff, Decl(InferFromReturnsInContextSensitive1.ts, 84, 4)) + +})); + +const res3 = test1((_something) => ({ +>res3 : Symbol(res3, Decl(InferFromReturnsInContextSensitive1.ts, 88, 5)) +>test1 : Symbol(test1, Decl(InferFromReturnsInContextSensitive1.ts, 64, 2)) +>_something : Symbol(_something, Decl(InferFromReturnsInContextSensitive1.ts, 88, 20)) + + stuff: "foo", +>stuff : Symbol(stuff, Decl(InferFromReturnsInContextSensitive1.ts, 88, 37)) + + consume: () => { +>consume : Symbol(consume, Decl(InferFromReturnsInContextSensitive1.ts, 89, 15)) + + return (_something) => ({ +>_something : Symbol(_something, Decl(InferFromReturnsInContextSensitive1.ts, 91, 12)) + + stuff2: 42, +>stuff2 : Symbol(stuff2, Decl(InferFromReturnsInContextSensitive1.ts, 91, 29)) + + consume2: (arg2) => {}, +>consume2 : Symbol(consume2, Decl(InferFromReturnsInContextSensitive1.ts, 92, 17)) +>arg2 : Symbol(arg2, Decl(InferFromReturnsInContextSensitive1.ts, 93, 17)) + + }); + }, +})); + +const res4 = test1((_something) => ({ +>res4 : Symbol(res4, Decl(InferFromReturnsInContextSensitive1.ts, 98, 5)) +>test1 : Symbol(test1, Decl(InferFromReturnsInContextSensitive1.ts, 64, 2)) +>_something : Symbol(_something, Decl(InferFromReturnsInContextSensitive1.ts, 98, 20)) + + consume: () => { +>consume : Symbol(consume, Decl(InferFromReturnsInContextSensitive1.ts, 98, 37)) + + return (_something) => ({ +>_something : Symbol(_something, Decl(InferFromReturnsInContextSensitive1.ts, 100, 12)) + + consume2: (arg2) => {}, +>consume2 : Symbol(consume2, Decl(InferFromReturnsInContextSensitive1.ts, 100, 29)) +>arg2 : Symbol(arg2, Decl(InferFromReturnsInContextSensitive1.ts, 101, 17)) + + stuff2: 42, +>stuff2 : Symbol(stuff2, Decl(InferFromReturnsInContextSensitive1.ts, 101, 29)) + + }); + }, + stuff: "foo", +>stuff : Symbol(stuff, Decl(InferFromReturnsInContextSensitive1.ts, 104, 4)) + +})); + +const res5 = test1((_something) => ({ +>res5 : Symbol(res5, Decl(InferFromReturnsInContextSensitive1.ts, 108, 5)) +>test1 : Symbol(test1, Decl(InferFromReturnsInContextSensitive1.ts, 64, 2)) +>_something : Symbol(_something, Decl(InferFromReturnsInContextSensitive1.ts, 108, 20)) + + stuff: "foo", +>stuff : Symbol(stuff, Decl(InferFromReturnsInContextSensitive1.ts, 108, 37)) + + consume: () => { +>consume : Symbol(consume, Decl(InferFromReturnsInContextSensitive1.ts, 109, 15)) + + return () => ({ + stuff2: 42, +>stuff2 : Symbol(stuff2, Decl(InferFromReturnsInContextSensitive1.ts, 111, 19)) + + consume2: (arg2) => {}, +>consume2 : Symbol(consume2, Decl(InferFromReturnsInContextSensitive1.ts, 112, 17)) +>arg2 : Symbol(arg2, Decl(InferFromReturnsInContextSensitive1.ts, 113, 17)) + + }); + }, +})); + +const res6 = test1((_something) => ({ +>res6 : Symbol(res6, Decl(InferFromReturnsInContextSensitive1.ts, 118, 5)) +>test1 : Symbol(test1, Decl(InferFromReturnsInContextSensitive1.ts, 64, 2)) +>_something : Symbol(_something, Decl(InferFromReturnsInContextSensitive1.ts, 118, 20)) + + consume: () => { +>consume : Symbol(consume, Decl(InferFromReturnsInContextSensitive1.ts, 118, 37)) + + return () => ({ + consume2: (arg2) => {}, +>consume2 : Symbol(consume2, Decl(InferFromReturnsInContextSensitive1.ts, 120, 19)) +>arg2 : Symbol(arg2, Decl(InferFromReturnsInContextSensitive1.ts, 121, 17)) + + stuff2: 42, +>stuff2 : Symbol(stuff2, Decl(InferFromReturnsInContextSensitive1.ts, 121, 29)) + + }); + }, + stuff: "foo", +>stuff : Symbol(stuff, Decl(InferFromReturnsInContextSensitive1.ts, 124, 4)) + +})); + +const res7 = test1((_something) => ({ +>res7 : Symbol(res7, Decl(InferFromReturnsInContextSensitive1.ts, 128, 5)) +>test1 : Symbol(test1, Decl(InferFromReturnsInContextSensitive1.ts, 64, 2)) +>_something : Symbol(_something, Decl(InferFromReturnsInContextSensitive1.ts, 128, 20)) + + stuff: "foo", +>stuff : Symbol(stuff, Decl(InferFromReturnsInContextSensitive1.ts, 128, 37)) + + consume: () => { +>consume : Symbol(consume, Decl(InferFromReturnsInContextSensitive1.ts, 129, 15)) + + return () => ({ + stuff2: 42, +>stuff2 : Symbol(stuff2, Decl(InferFromReturnsInContextSensitive1.ts, 131, 19)) + + consume2: () => {}, +>consume2 : Symbol(consume2, Decl(InferFromReturnsInContextSensitive1.ts, 132, 17)) + + }); + }, +})); + +const res8 = test1((_something) => ({ +>res8 : Symbol(res8, Decl(InferFromReturnsInContextSensitive1.ts, 138, 5)) +>test1 : Symbol(test1, Decl(InferFromReturnsInContextSensitive1.ts, 64, 2)) +>_something : Symbol(_something, Decl(InferFromReturnsInContextSensitive1.ts, 138, 20)) + + consume: () => { +>consume : Symbol(consume, Decl(InferFromReturnsInContextSensitive1.ts, 138, 37)) + + return () => ({ + consume2: () => {}, +>consume2 : Symbol(consume2, Decl(InferFromReturnsInContextSensitive1.ts, 140, 19)) + + stuff2: 42, +>stuff2 : Symbol(stuff2, Decl(InferFromReturnsInContextSensitive1.ts, 141, 25)) + + }); + }, + stuff: "foo", +>stuff : Symbol(stuff, Decl(InferFromReturnsInContextSensitive1.ts, 144, 4)) + })); diff --git a/tests/baselines/reference/InferFromReturnsInContextSensitive1.types b/tests/baselines/reference/InferFromReturnsInContextSensitive1.types index 93de793ca595f..c3fe947d1e083 100644 --- a/tests/baselines/reference/InferFromReturnsInContextSensitive1.types +++ b/tests/baselines/reference/InferFromReturnsInContextSensitive1.types @@ -76,6 +76,46 @@ create((arg) => ({ })); +create((arg) => ({ +>create((arg) => ({ onEnd: (context) => {}, onStart: () => ({ time: new Date() }),})) : Options<{ time: Date; }> +> : ^^^^^^^^^^^^^^^^^^^^^^^^ +>create : (builder: (arg: boolean) => Options) => Options +> : ^ ^^ ^^ ^^^^^^^^^^^^^^^^^^^^^^ +>(arg) => ({ onEnd: (context) => {}, onStart: () => ({ time: new Date() }),}) : (arg: boolean) => { onEnd: (context: { time: Date; }) => void; onStart: () => { time: Date; }; } +> : ^ ^^^^^^^^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +>arg : boolean +> : ^^^^^^^ +>({ onEnd: (context) => {}, onStart: () => ({ time: new Date() }),}) : { onEnd: (context: { time: Date; }) => void; onStart: () => { time: Date; }; } +> : ^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +>{ onEnd: (context) => {}, onStart: () => ({ time: new Date() }),} : { onEnd: (context: { time: Date; }) => void; onStart: () => { time: Date; }; } +> : ^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + + onEnd: (context) => {}, +>onEnd : (context: { time: Date; }) => void +> : ^ ^^^^^^^^^^^^^^^^^^^^^^^^^^ +>(context) => {} : (context: { time: Date; }) => void +> : ^ ^^^^^^^^^^^^^^^^^^^^^^^^^^ +>context : { time: Date; } +> : ^^^^^^^^^^^^^^^ + + onStart: () => ({ time: new Date() }), +>onStart : () => { time: Date; } +> : ^^^^^^^^^^^^^^^^^^^^^ +>() => ({ time: new Date() }) : () => { time: Date; } +> : ^^^^^^^^^^^^^^^^^^^^^ +>({ time: new Date() }) : { time: Date; } +> : ^^^^^^^^^^^^^^^ +>{ time: new Date() } : { time: Date; } +> : ^^^^^^^^^^^^^^^ +>time : Date +> : ^^^^ +>new Date() : Date +> : ^^^^ +>Date : DateConstructor +> : ^^^^^^^^^^^^^^^ + +})); + // https://github.com/microsoft/TypeScript/issues/57021 type Schema = Record; @@ -100,9 +140,9 @@ type StepFunction = (anything: unknown) => { }; -function step1( ->step1 : (stepVal: StepFunction) => StepFunction -> : ^ ^^^^^^^^^ ^^^^^^^^^^^ ^^ ^^^^^ +function step( +>step : (stepVal: StepFunction) => StepFunction +> : ^ ^^^^^^^^^ ^^^^^^^^^^^ ^^ ^^^^^ stepVal: StepFunction, >stepVal : StepFunction @@ -114,13 +154,13 @@ function step1( > : ^^^^^^^^^^^^^^^^^^^^^ } -const stepResult1 = step1((_something) => ({ +const stepResult1 = step((_something) => ({ >stepResult1 : StepFunction<{ attribute: string; }> > : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ->step1((_something) => ({ schema: { attribute: "anything", }, toAnswers: (keys) => { type Test = string extends typeof keys ? never : "true"; const test: Test = "true"; // ok return { test }; },})) : StepFunction<{ attribute: string; }> -> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ->step1 : (stepVal: StepFunction) => StepFunction -> : ^ ^^^^^^^^^ ^^^^^^^^^^^ ^^ ^^^^^ +>step((_something) => ({ schema: { attribute: "anything", }, toAnswers: (keys) => { type Test = string extends typeof keys ? never : "true"; const test: Test = "true"; // ok return { test }; },})) : StepFunction<{ attribute: string; }> +> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +>step : (stepVal: StepFunction) => StepFunction +> : ^ ^^^^^^^^^ ^^^^^^^^^^^ ^^ ^^^^^ >(_something) => ({ schema: { attribute: "anything", }, toAnswers: (keys) => { type Test = string extends typeof keys ? never : "true"; const test: Test = "true"; // ok return { test }; },}) : (_something: unknown) => { schema: { attribute: string; }; toAnswers: (keys: "attribute") => { test: "true"; }; } > : ^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ >_something : unknown @@ -172,3 +212,538 @@ const stepResult1 = step1((_something) => ({ }, })); +const stepResult2 = step((_something) => ({ +>stepResult2 : StepFunction<{ attribute: string; }> +> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +>step((_something) => ({ toAnswers: (keys) => { type Test = string extends typeof keys ? never : "true"; const test: Test = "true"; // ok return { test }; }, schema: { attribute: "anything", },})) : StepFunction<{ attribute: string; }> +> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +>step : (stepVal: StepFunction) => StepFunction +> : ^ ^^^^^^^^^ ^^^^^^^^^^^ ^^ ^^^^^ +>(_something) => ({ toAnswers: (keys) => { type Test = string extends typeof keys ? never : "true"; const test: Test = "true"; // ok return { test }; }, schema: { attribute: "anything", },}) : (_something: unknown) => { toAnswers: (keys: "attribute") => { test: "true"; }; schema: { attribute: string; }; } +> : ^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +>_something : unknown +> : ^^^^^^^ +>({ toAnswers: (keys) => { type Test = string extends typeof keys ? never : "true"; const test: Test = "true"; // ok return { test }; }, schema: { attribute: "anything", },}) : { toAnswers: (keys: "attribute") => { test: "true"; }; schema: { attribute: string; }; } +> : ^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +>{ toAnswers: (keys) => { type Test = string extends typeof keys ? never : "true"; const test: Test = "true"; // ok return { test }; }, schema: { attribute: "anything", },} : { toAnswers: (keys: "attribute") => { test: "true"; }; schema: { attribute: string; }; } +> : ^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + + toAnswers: (keys) => { +>toAnswers : (keys: "attribute") => { test: "true"; } +> : ^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +>(keys) => { type Test = string extends typeof keys ? never : "true"; const test: Test = "true"; // ok return { test }; } : (keys: "attribute") => { test: "true"; } +> : ^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +>keys : "attribute" +> : ^^^^^^^^^^^ + + type Test = string extends typeof keys ? never : "true"; +>Test : "true" +> : ^^^^^^ +>keys : "attribute" +> : ^^^^^^^^^^^ + + const test: Test = "true"; // ok +>test : "true" +> : ^^^^^^ +>"true" : "true" +> : ^^^^^^ + + return { test }; +>{ test } : { test: "true"; } +> : ^^^^^^^^^^^^^^^^^ +>test : "true" +> : ^^^^^^ + + }, + schema: { +>schema : { attribute: string; } +> : ^^^^^^^^^^^^^^^^^^^^^^ +>{ attribute: "anything", } : { attribute: string; } +> : ^^^^^^^^^^^^^^^^^^^^^^ + + attribute: "anything", +>attribute : string +> : ^^^^^^ +>"anything" : "anything" +> : ^^^^^^^^^^ + + }, +})); + +type Fn1 = (anything: unknown) => { +>Fn1 : Fn1 +> : ^^^^^^^^^^ +>anything : unknown +> : ^^^^^^^ + + stuff: T; +>stuff : T +> : ^ + + consume: (arg: T) => (anything: unknown) => { +>consume : (arg: T) => (anything: unknown) => { stuff2: T2; consume2: (arg: T2) => void; } +> : ^ ^^ ^^^^^ +>arg : T +> : ^ +>anything : unknown +> : ^^^^^^^ + + stuff2: T2; +>stuff2 : T2 +> : ^^ + + consume2: (arg: T2) => void; +>consume2 : (arg: T2) => void +> : ^ ^^ ^^^^^ +>arg : T2 +> : ^^ + + }; +}; + +declare function test1(fn: Fn1): [T, T2]; +>test1 : (fn: Fn1) => [T, T2] +> : ^ ^^ ^^ ^^ ^^^^^ +>fn : Fn1 +> : ^^^^^^^^^^ + +const res1 = test1((_something) => ({ +>res1 : [string, number] +> : ^^^^^^^^^^^^^^^^ +>test1((_something) => ({ stuff: "foo", consume: (arg) => { return (_something) => ({ stuff2: 42, consume2: (arg2) => {}, }); },})) : [string, number] +> : ^^^^^^^^^^^^^^^^ +>test1 : (fn: Fn1) => [T, T2] +> : ^ ^^ ^^ ^^ ^^^^^ +>(_something) => ({ stuff: "foo", consume: (arg) => { return (_something) => ({ stuff2: 42, consume2: (arg2) => {}, }); },}) : (_something: unknown) => { stuff: string; consume: (arg: string) => (_something: unknown) => { stuff2: number; consume2: (arg2: number) => void; }; } +> : ^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^ +>_something : unknown +> : ^^^^^^^ +>({ stuff: "foo", consume: (arg) => { return (_something) => ({ stuff2: 42, consume2: (arg2) => {}, }); },}) : { stuff: string; consume: (arg: string) => (_something: unknown) => { stuff2: number; consume2: (arg2: number) => void; }; } +> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^ +>{ stuff: "foo", consume: (arg) => { return (_something) => ({ stuff2: 42, consume2: (arg2) => {}, }); },} : { stuff: string; consume: (arg: string) => (_something: unknown) => { stuff2: number; consume2: (arg2: number) => void; }; } +> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^ + + stuff: "foo", +>stuff : string +> : ^^^^^^ +>"foo" : "foo" +> : ^^^^^ + + consume: (arg) => { +>consume : (arg: string) => (_something: unknown) => { stuff2: number; consume2: (arg2: number) => void; } +> : ^ ^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^ +>(arg) => { return (_something) => ({ stuff2: 42, consume2: (arg2) => {}, }); } : (arg: string) => (_something: unknown) => { stuff2: number; consume2: (arg2: number) => void; } +> : ^ ^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^ +>arg : string +> : ^^^^^^ + + return (_something) => ({ +>(_something) => ({ stuff2: 42, consume2: (arg2) => {}, }) : (_something: unknown) => { stuff2: number; consume2: (arg2: number) => void; } +> : ^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^ +>_something : unknown +> : ^^^^^^^ +>({ stuff2: 42, consume2: (arg2) => {}, }) : { stuff2: number; consume2: (arg2: number) => void; } +> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^ +>{ stuff2: 42, consume2: (arg2) => {}, } : { stuff2: number; consume2: (arg2: number) => void; } +> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^ + + stuff2: 42, +>stuff2 : number +> : ^^^^^^ +>42 : 42 +> : ^^ + + consume2: (arg2) => {}, +>consume2 : (arg2: number) => void +> : ^ ^^^^^^^^^^^^^^^^^ +>(arg2) => {} : (arg2: number) => void +> : ^ ^^^^^^^^^^^^^^^^^ +>arg2 : number +> : ^^^^^^ + + }); + }, +})); + +const res2 = test1((_something) => ({ +>res2 : [string, number] +> : ^^^^^^^^^^^^^^^^ +>test1((_something) => ({ consume: (arg) => { return (_something) => ({ consume2: (arg2) => {}, stuff2: 42, }); }, stuff: "foo",})) : [string, number] +> : ^^^^^^^^^^^^^^^^ +>test1 : (fn: Fn1) => [T, T2] +> : ^ ^^ ^^ ^^ ^^^^^ +>(_something) => ({ consume: (arg) => { return (_something) => ({ consume2: (arg2) => {}, stuff2: 42, }); }, stuff: "foo",}) : (_something: unknown) => { consume: (arg: string) => (_something: unknown) => { consume2: (arg2: number) => void; stuff2: number; }; stuff: string; } +> : ^ ^^^^^^^^^^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +>_something : unknown +> : ^^^^^^^ +>({ consume: (arg) => { return (_something) => ({ consume2: (arg2) => {}, stuff2: 42, }); }, stuff: "foo",}) : { consume: (arg: string) => (_something: unknown) => { consume2: (arg2: number) => void; stuff2: number; }; stuff: string; } +> : ^^^^^^^^^^^^ ^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +>{ consume: (arg) => { return (_something) => ({ consume2: (arg2) => {}, stuff2: 42, }); }, stuff: "foo",} : { consume: (arg: string) => (_something: unknown) => { consume2: (arg2: number) => void; stuff2: number; }; stuff: string; } +> : ^^^^^^^^^^^^ ^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + + consume: (arg) => { +>consume : (arg: string) => (_something: unknown) => { consume2: (arg2: number) => void; stuff2: number; } +> : ^ ^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +>(arg) => { return (_something) => ({ consume2: (arg2) => {}, stuff2: 42, }); } : (arg: string) => (_something: unknown) => { consume2: (arg2: number) => void; stuff2: number; } +> : ^ ^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +>arg : string +> : ^^^^^^ + + return (_something) => ({ +>(_something) => ({ consume2: (arg2) => {}, stuff2: 42, }) : (_something: unknown) => { consume2: (arg2: number) => void; stuff2: number; } +> : ^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +>_something : unknown +> : ^^^^^^^ +>({ consume2: (arg2) => {}, stuff2: 42, }) : { consume2: (arg2: number) => void; stuff2: number; } +> : ^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +>{ consume2: (arg2) => {}, stuff2: 42, } : { consume2: (arg2: number) => void; stuff2: number; } +> : ^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + + consume2: (arg2) => {}, +>consume2 : (arg2: number) => void +> : ^ ^^^^^^^^^^^^^^^^^ +>(arg2) => {} : (arg2: number) => void +> : ^ ^^^^^^^^^^^^^^^^^ +>arg2 : number +> : ^^^^^^ + + stuff2: 42, +>stuff2 : number +> : ^^^^^^ +>42 : 42 +> : ^^ + + }); + }, + stuff: "foo", +>stuff : string +> : ^^^^^^ +>"foo" : "foo" +> : ^^^^^ + +})); + +const res3 = test1((_something) => ({ +>res3 : [string, number] +> : ^^^^^^^^^^^^^^^^ +>test1((_something) => ({ stuff: "foo", consume: () => { return (_something) => ({ stuff2: 42, consume2: (arg2) => {}, }); },})) : [string, number] +> : ^^^^^^^^^^^^^^^^ +>test1 : (fn: Fn1) => [T, T2] +> : ^ ^^ ^^ ^^ ^^^^^ +>(_something) => ({ stuff: "foo", consume: () => { return (_something) => ({ stuff2: 42, consume2: (arg2) => {}, }); },}) : (_something: unknown) => { stuff: string; consume: () => (_something: unknown) => { stuff2: number; consume2: (arg2: number) => void; }; } +> : ^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^ +>_something : unknown +> : ^^^^^^^ +>({ stuff: "foo", consume: () => { return (_something) => ({ stuff2: 42, consume2: (arg2) => {}, }); },}) : { stuff: string; consume: () => (_something: unknown) => { stuff2: number; consume2: (arg2: number) => void; }; } +> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^ +>{ stuff: "foo", consume: () => { return (_something) => ({ stuff2: 42, consume2: (arg2) => {}, }); },} : { stuff: string; consume: () => (_something: unknown) => { stuff2: number; consume2: (arg2: number) => void; }; } +> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^ + + stuff: "foo", +>stuff : string +> : ^^^^^^ +>"foo" : "foo" +> : ^^^^^ + + consume: () => { +>consume : () => (_something: unknown) => { stuff2: number; consume2: (arg2: number) => void; } +> : ^^^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^ +>() => { return (_something) => ({ stuff2: 42, consume2: (arg2) => {}, }); } : () => (_something: unknown) => { stuff2: number; consume2: (arg2: number) => void; } +> : ^^^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^ + + return (_something) => ({ +>(_something) => ({ stuff2: 42, consume2: (arg2) => {}, }) : (_something: unknown) => { stuff2: number; consume2: (arg2: number) => void; } +> : ^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^ +>_something : unknown +> : ^^^^^^^ +>({ stuff2: 42, consume2: (arg2) => {}, }) : { stuff2: number; consume2: (arg2: number) => void; } +> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^ +>{ stuff2: 42, consume2: (arg2) => {}, } : { stuff2: number; consume2: (arg2: number) => void; } +> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^ + + stuff2: 42, +>stuff2 : number +> : ^^^^^^ +>42 : 42 +> : ^^ + + consume2: (arg2) => {}, +>consume2 : (arg2: number) => void +> : ^ ^^^^^^^^^^^^^^^^^ +>(arg2) => {} : (arg2: number) => void +> : ^ ^^^^^^^^^^^^^^^^^ +>arg2 : number +> : ^^^^^^ + + }); + }, +})); + +const res4 = test1((_something) => ({ +>res4 : [string, number] +> : ^^^^^^^^^^^^^^^^ +>test1((_something) => ({ consume: () => { return (_something) => ({ consume2: (arg2) => {}, stuff2: 42, }); }, stuff: "foo",})) : [string, number] +> : ^^^^^^^^^^^^^^^^ +>test1 : (fn: Fn1) => [T, T2] +> : ^ ^^ ^^ ^^ ^^^^^ +>(_something) => ({ consume: () => { return (_something) => ({ consume2: (arg2) => {}, stuff2: 42, }); }, stuff: "foo",}) : (_something: unknown) => { consume: () => (_something: unknown) => { consume2: (arg2: number) => void; stuff2: number; }; stuff: string; } +> : ^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +>_something : unknown +> : ^^^^^^^ +>({ consume: () => { return (_something) => ({ consume2: (arg2) => {}, stuff2: 42, }); }, stuff: "foo",}) : { consume: () => (_something: unknown) => { consume2: (arg2: number) => void; stuff2: number; }; stuff: string; } +> : ^^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +>{ consume: () => { return (_something) => ({ consume2: (arg2) => {}, stuff2: 42, }); }, stuff: "foo",} : { consume: () => (_something: unknown) => { consume2: (arg2: number) => void; stuff2: number; }; stuff: string; } +> : ^^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + + consume: () => { +>consume : () => (_something: unknown) => { consume2: (arg2: number) => void; stuff2: number; } +> : ^^^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +>() => { return (_something) => ({ consume2: (arg2) => {}, stuff2: 42, }); } : () => (_something: unknown) => { consume2: (arg2: number) => void; stuff2: number; } +> : ^^^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + + return (_something) => ({ +>(_something) => ({ consume2: (arg2) => {}, stuff2: 42, }) : (_something: unknown) => { consume2: (arg2: number) => void; stuff2: number; } +> : ^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +>_something : unknown +> : ^^^^^^^ +>({ consume2: (arg2) => {}, stuff2: 42, }) : { consume2: (arg2: number) => void; stuff2: number; } +> : ^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +>{ consume2: (arg2) => {}, stuff2: 42, } : { consume2: (arg2: number) => void; stuff2: number; } +> : ^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + + consume2: (arg2) => {}, +>consume2 : (arg2: number) => void +> : ^ ^^^^^^^^^^^^^^^^^ +>(arg2) => {} : (arg2: number) => void +> : ^ ^^^^^^^^^^^^^^^^^ +>arg2 : number +> : ^^^^^^ + + stuff2: 42, +>stuff2 : number +> : ^^^^^^ +>42 : 42 +> : ^^ + + }); + }, + stuff: "foo", +>stuff : string +> : ^^^^^^ +>"foo" : "foo" +> : ^^^^^ + +})); + +const res5 = test1((_something) => ({ +>res5 : [string, number] +> : ^^^^^^^^^^^^^^^^ +>test1((_something) => ({ stuff: "foo", consume: () => { return () => ({ stuff2: 42, consume2: (arg2) => {}, }); },})) : [string, number] +> : ^^^^^^^^^^^^^^^^ +>test1 : (fn: Fn1) => [T, T2] +> : ^ ^^ ^^ ^^ ^^^^^ +>(_something) => ({ stuff: "foo", consume: () => { return () => ({ stuff2: 42, consume2: (arg2) => {}, }); },}) : (_something: unknown) => { stuff: string; consume: () => () => { stuff2: number; consume2: (arg2: number) => void; }; } +> : ^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^ +>_something : unknown +> : ^^^^^^^ +>({ stuff: "foo", consume: () => { return () => ({ stuff2: 42, consume2: (arg2) => {}, }); },}) : { stuff: string; consume: () => () => { stuff2: number; consume2: (arg2: number) => void; }; } +> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^ +>{ stuff: "foo", consume: () => { return () => ({ stuff2: 42, consume2: (arg2) => {}, }); },} : { stuff: string; consume: () => () => { stuff2: number; consume2: (arg2: number) => void; }; } +> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^ + + stuff: "foo", +>stuff : string +> : ^^^^^^ +>"foo" : "foo" +> : ^^^^^ + + consume: () => { +>consume : () => () => { stuff2: number; consume2: (arg2: number) => void; } +> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^ +>() => { return () => ({ stuff2: 42, consume2: (arg2) => {}, }); } : () => () => { stuff2: number; consume2: (arg2: number) => void; } +> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^ + + return () => ({ +>() => ({ stuff2: 42, consume2: (arg2) => {}, }) : () => { stuff2: number; consume2: (arg2: number) => void; } +> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^ +>({ stuff2: 42, consume2: (arg2) => {}, }) : { stuff2: number; consume2: (arg2: number) => void; } +> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^ +>{ stuff2: 42, consume2: (arg2) => {}, } : { stuff2: number; consume2: (arg2: number) => void; } +> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^ + + stuff2: 42, +>stuff2 : number +> : ^^^^^^ +>42 : 42 +> : ^^ + + consume2: (arg2) => {}, +>consume2 : (arg2: number) => void +> : ^ ^^^^^^^^^^^^^^^^^ +>(arg2) => {} : (arg2: number) => void +> : ^ ^^^^^^^^^^^^^^^^^ +>arg2 : number +> : ^^^^^^ + + }); + }, +})); + +const res6 = test1((_something) => ({ +>res6 : [string, number] +> : ^^^^^^^^^^^^^^^^ +>test1((_something) => ({ consume: () => { return () => ({ consume2: (arg2) => {}, stuff2: 42, }); }, stuff: "foo",})) : [string, number] +> : ^^^^^^^^^^^^^^^^ +>test1 : (fn: Fn1) => [T, T2] +> : ^ ^^ ^^ ^^ ^^^^^ +>(_something) => ({ consume: () => { return () => ({ consume2: (arg2) => {}, stuff2: 42, }); }, stuff: "foo",}) : (_something: unknown) => { consume: () => () => { consume2: (arg2: number) => void; stuff2: number; }; stuff: string; } +> : ^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +>_something : unknown +> : ^^^^^^^ +>({ consume: () => { return () => ({ consume2: (arg2) => {}, stuff2: 42, }); }, stuff: "foo",}) : { consume: () => () => { consume2: (arg2: number) => void; stuff2: number; }; stuff: string; } +> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +>{ consume: () => { return () => ({ consume2: (arg2) => {}, stuff2: 42, }); }, stuff: "foo",} : { consume: () => () => { consume2: (arg2: number) => void; stuff2: number; }; stuff: string; } +> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + + consume: () => { +>consume : () => () => { consume2: (arg2: number) => void; stuff2: number; } +> : ^^^^^^^^^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +>() => { return () => ({ consume2: (arg2) => {}, stuff2: 42, }); } : () => () => { consume2: (arg2: number) => void; stuff2: number; } +> : ^^^^^^^^^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + + return () => ({ +>() => ({ consume2: (arg2) => {}, stuff2: 42, }) : () => { consume2: (arg2: number) => void; stuff2: number; } +> : ^^^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +>({ consume2: (arg2) => {}, stuff2: 42, }) : { consume2: (arg2: number) => void; stuff2: number; } +> : ^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +>{ consume2: (arg2) => {}, stuff2: 42, } : { consume2: (arg2: number) => void; stuff2: number; } +> : ^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + + consume2: (arg2) => {}, +>consume2 : (arg2: number) => void +> : ^ ^^^^^^^^^^^^^^^^^ +>(arg2) => {} : (arg2: number) => void +> : ^ ^^^^^^^^^^^^^^^^^ +>arg2 : number +> : ^^^^^^ + + stuff2: 42, +>stuff2 : number +> : ^^^^^^ +>42 : 42 +> : ^^ + + }); + }, + stuff: "foo", +>stuff : string +> : ^^^^^^ +>"foo" : "foo" +> : ^^^^^ + +})); + +const res7 = test1((_something) => ({ +>res7 : [string, number] +> : ^^^^^^^^^^^^^^^^ +>test1((_something) => ({ stuff: "foo", consume: () => { return () => ({ stuff2: 42, consume2: () => {}, }); },})) : [string, number] +> : ^^^^^^^^^^^^^^^^ +>test1 : (fn: Fn1) => [T, T2] +> : ^ ^^ ^^ ^^ ^^^^^ +>(_something) => ({ stuff: "foo", consume: () => { return () => ({ stuff2: 42, consume2: () => {}, }); },}) : (_something: unknown) => { stuff: string; consume: () => () => { stuff2: number; consume2: () => void; }; } +> : ^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +>_something : unknown +> : ^^^^^^^ +>({ stuff: "foo", consume: () => { return () => ({ stuff2: 42, consume2: () => {}, }); },}) : { stuff: string; consume: () => () => { stuff2: number; consume2: () => void; }; } +> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +>{ stuff: "foo", consume: () => { return () => ({ stuff2: 42, consume2: () => {}, }); },} : { stuff: string; consume: () => () => { stuff2: number; consume2: () => void; }; } +> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + + stuff: "foo", +>stuff : string +> : ^^^^^^ +>"foo" : "foo" +> : ^^^^^ + + consume: () => { +>consume : () => () => { stuff2: number; consume2: () => void; } +> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +>() => { return () => ({ stuff2: 42, consume2: () => {}, }); } : () => () => { stuff2: number; consume2: () => void; } +> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + + return () => ({ +>() => ({ stuff2: 42, consume2: () => {}, }) : () => { stuff2: number; consume2: () => void; } +> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +>({ stuff2: 42, consume2: () => {}, }) : { stuff2: number; consume2: () => void; } +> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +>{ stuff2: 42, consume2: () => {}, } : { stuff2: number; consume2: () => void; } +> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + + stuff2: 42, +>stuff2 : number +> : ^^^^^^ +>42 : 42 +> : ^^ + + consume2: () => {}, +>consume2 : () => void +> : ^^^^^^^^^^ +>() => {} : () => void +> : ^^^^^^^^^^ + + }); + }, +})); + +const res8 = test1((_something) => ({ +>res8 : [string, number] +> : ^^^^^^^^^^^^^^^^ +>test1((_something) => ({ consume: () => { return () => ({ consume2: () => {}, stuff2: 42, }); }, stuff: "foo",})) : [string, number] +> : ^^^^^^^^^^^^^^^^ +>test1 : (fn: Fn1) => [T, T2] +> : ^ ^^ ^^ ^^ ^^^^^ +>(_something) => ({ consume: () => { return () => ({ consume2: () => {}, stuff2: 42, }); }, stuff: "foo",}) : (_something: unknown) => { consume: () => () => { consume2: () => void; stuff2: number; }; stuff: string; } +> : ^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +>_something : unknown +> : ^^^^^^^ +>({ consume: () => { return () => ({ consume2: () => {}, stuff2: 42, }); }, stuff: "foo",}) : { consume: () => () => { consume2: () => void; stuff2: number; }; stuff: string; } +> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +>{ consume: () => { return () => ({ consume2: () => {}, stuff2: 42, }); }, stuff: "foo",} : { consume: () => () => { consume2: () => void; stuff2: number; }; stuff: string; } +> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + + consume: () => { +>consume : () => () => { consume2: () => void; stuff2: number; } +> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +>() => { return () => ({ consume2: () => {}, stuff2: 42, }); } : () => () => { consume2: () => void; stuff2: number; } +> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + + return () => ({ +>() => ({ consume2: () => {}, stuff2: 42, }) : () => { consume2: () => void; stuff2: number; } +> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +>({ consume2: () => {}, stuff2: 42, }) : { consume2: () => void; stuff2: number; } +> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +>{ consume2: () => {}, stuff2: 42, } : { consume2: () => void; stuff2: number; } +> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + + consume2: () => {}, +>consume2 : () => void +> : ^^^^^^^^^^ +>() => {} : () => void +> : ^^^^^^^^^^ + + stuff2: 42, +>stuff2 : number +> : ^^^^^^ +>42 : 42 +> : ^^ + + }); + }, + stuff: "foo", +>stuff : string +> : ^^^^^^ +>"foo" : "foo" +> : ^^^^^ + +})); + diff --git a/tests/baselines/reference/intraExpressionInferencesInContextSensitive1.js b/tests/baselines/reference/intraExpressionInferencesInContextSensitive1.js index 760d687ebc55d..3da93cbc3d46b 100644 --- a/tests/baselines/reference/intraExpressionInferencesInContextSensitive1.js +++ b/tests/baselines/reference/intraExpressionInferencesInContextSensitive1.js @@ -38,6 +38,36 @@ const stepResult = step((_something) => ({ return { test }; }, })); + +type Fn1 = (anything: unknown) => { + produce: (arg: number) => T; + consume: (arg: T) => (anything: unknown) => { + produce2: (arg: number) => T2; + consume2: (arg: T2) => void; + }; +}; + +declare function test1(fn: Fn1): [T, T2]; + +const res1 = test1((_something) => ({ + produce: (input) => "foo", + consume: (arg) => { + return (_something) => ({ + produce2: (input) => 42, + consume2: (arg2) => {}, + }); + }, +})); + +const res2 = test1((_something) => ({ + produce: (input) => "foo", + consume: (arg) => { + return () => ({ + produce2: (input) => 42, + consume2: (arg2) => {}, + }); + }, +})); //// [intraExpressionInferencesInContextSensitive1.js] @@ -61,6 +91,24 @@ var stepResult = step(function (_something) { return ({ return { test: test }; }, }); }); +var res1 = test1(function (_something) { return ({ + produce: function (input) { return "foo"; }, + consume: function (arg) { + return function (_something) { return ({ + produce2: function (input) { return 42; }, + consume2: function (arg2) { }, + }); }; + }, +}); }); +var res2 = test1(function (_something) { return ({ + produce: function (input) { return "foo"; }, + consume: function (arg) { + return function () { return ({ + produce2: function (input) { return 42; }, + consume2: function (arg2) { }, + }); }; + }, +}); }); //// [intraExpressionInferencesInContextSensitive1.d.ts] @@ -78,3 +126,13 @@ declare function step(stepVal: StepFunction; +type Fn1 = (anything: unknown) => { + produce: (arg: number) => T; + consume: (arg: T) => (anything: unknown) => { + produce2: (arg: number) => T2; + consume2: (arg: T2) => void; + }; +}; +declare function test1(fn: Fn1): [T, T2]; +declare const res1: [string, number]; +declare const res2: [string, number]; diff --git a/tests/baselines/reference/intraExpressionInferencesInContextSensitive1.symbols b/tests/baselines/reference/intraExpressionInferencesInContextSensitive1.symbols index 6b124f51f738c..1452767c32b22 100644 --- a/tests/baselines/reference/intraExpressionInferencesInContextSensitive1.symbols +++ b/tests/baselines/reference/intraExpressionInferencesInContextSensitive1.symbols @@ -118,3 +118,98 @@ const stepResult = step((_something) => ({ }, })); +type Fn1 = (anything: unknown) => { +>Fn1 : Symbol(Fn1, Decl(intraExpressionInferencesInContextSensitive1.ts, 36, 4)) +>T : Symbol(T, Decl(intraExpressionInferencesInContextSensitive1.ts, 38, 9)) +>T2 : Symbol(T2, Decl(intraExpressionInferencesInContextSensitive1.ts, 38, 11)) +>anything : Symbol(anything, Decl(intraExpressionInferencesInContextSensitive1.ts, 38, 19)) + + produce: (arg: number) => T; +>produce : Symbol(produce, Decl(intraExpressionInferencesInContextSensitive1.ts, 38, 42)) +>arg : Symbol(arg, Decl(intraExpressionInferencesInContextSensitive1.ts, 39, 12)) +>T : Symbol(T, Decl(intraExpressionInferencesInContextSensitive1.ts, 38, 9)) + + consume: (arg: T) => (anything: unknown) => { +>consume : Symbol(consume, Decl(intraExpressionInferencesInContextSensitive1.ts, 39, 30)) +>arg : Symbol(arg, Decl(intraExpressionInferencesInContextSensitive1.ts, 40, 12)) +>T : Symbol(T, Decl(intraExpressionInferencesInContextSensitive1.ts, 38, 9)) +>anything : Symbol(anything, Decl(intraExpressionInferencesInContextSensitive1.ts, 40, 24)) + + produce2: (arg: number) => T2; +>produce2 : Symbol(produce2, Decl(intraExpressionInferencesInContextSensitive1.ts, 40, 47)) +>arg : Symbol(arg, Decl(intraExpressionInferencesInContextSensitive1.ts, 41, 15)) +>T2 : Symbol(T2, Decl(intraExpressionInferencesInContextSensitive1.ts, 38, 11)) + + consume2: (arg: T2) => void; +>consume2 : Symbol(consume2, Decl(intraExpressionInferencesInContextSensitive1.ts, 41, 34)) +>arg : Symbol(arg, Decl(intraExpressionInferencesInContextSensitive1.ts, 42, 15)) +>T2 : Symbol(T2, Decl(intraExpressionInferencesInContextSensitive1.ts, 38, 11)) + + }; +}; + +declare function test1(fn: Fn1): [T, T2]; +>test1 : Symbol(test1, Decl(intraExpressionInferencesInContextSensitive1.ts, 44, 2)) +>T : Symbol(T, Decl(intraExpressionInferencesInContextSensitive1.ts, 46, 23)) +>T2 : Symbol(T2, Decl(intraExpressionInferencesInContextSensitive1.ts, 46, 25)) +>fn : Symbol(fn, Decl(intraExpressionInferencesInContextSensitive1.ts, 46, 30)) +>Fn1 : Symbol(Fn1, Decl(intraExpressionInferencesInContextSensitive1.ts, 36, 4)) +>T : Symbol(T, Decl(intraExpressionInferencesInContextSensitive1.ts, 46, 23)) +>T2 : Symbol(T2, Decl(intraExpressionInferencesInContextSensitive1.ts, 46, 25)) +>T : Symbol(T, Decl(intraExpressionInferencesInContextSensitive1.ts, 46, 23)) +>T2 : Symbol(T2, Decl(intraExpressionInferencesInContextSensitive1.ts, 46, 25)) + +const res1 = test1((_something) => ({ +>res1 : Symbol(res1, Decl(intraExpressionInferencesInContextSensitive1.ts, 48, 5)) +>test1 : Symbol(test1, Decl(intraExpressionInferencesInContextSensitive1.ts, 44, 2)) +>_something : Symbol(_something, Decl(intraExpressionInferencesInContextSensitive1.ts, 48, 20)) + + produce: (input) => "foo", +>produce : Symbol(produce, Decl(intraExpressionInferencesInContextSensitive1.ts, 48, 37)) +>input : Symbol(input, Decl(intraExpressionInferencesInContextSensitive1.ts, 49, 12)) + + consume: (arg) => { +>consume : Symbol(consume, Decl(intraExpressionInferencesInContextSensitive1.ts, 49, 28)) +>arg : Symbol(arg, Decl(intraExpressionInferencesInContextSensitive1.ts, 50, 12)) + + return (_something) => ({ +>_something : Symbol(_something, Decl(intraExpressionInferencesInContextSensitive1.ts, 51, 12)) + + produce2: (input) => 42, +>produce2 : Symbol(produce2, Decl(intraExpressionInferencesInContextSensitive1.ts, 51, 29)) +>input : Symbol(input, Decl(intraExpressionInferencesInContextSensitive1.ts, 52, 17)) + + consume2: (arg2) => {}, +>consume2 : Symbol(consume2, Decl(intraExpressionInferencesInContextSensitive1.ts, 52, 30)) +>arg2 : Symbol(arg2, Decl(intraExpressionInferencesInContextSensitive1.ts, 53, 17)) + + }); + }, +})); + +const res2 = test1((_something) => ({ +>res2 : Symbol(res2, Decl(intraExpressionInferencesInContextSensitive1.ts, 58, 5)) +>test1 : Symbol(test1, Decl(intraExpressionInferencesInContextSensitive1.ts, 44, 2)) +>_something : Symbol(_something, Decl(intraExpressionInferencesInContextSensitive1.ts, 58, 20)) + + produce: (input) => "foo", +>produce : Symbol(produce, Decl(intraExpressionInferencesInContextSensitive1.ts, 58, 37)) +>input : Symbol(input, Decl(intraExpressionInferencesInContextSensitive1.ts, 59, 12)) + + consume: (arg) => { +>consume : Symbol(consume, Decl(intraExpressionInferencesInContextSensitive1.ts, 59, 28)) +>arg : Symbol(arg, Decl(intraExpressionInferencesInContextSensitive1.ts, 60, 12)) + + return () => ({ + produce2: (input) => 42, +>produce2 : Symbol(produce2, Decl(intraExpressionInferencesInContextSensitive1.ts, 61, 19)) +>input : Symbol(input, Decl(intraExpressionInferencesInContextSensitive1.ts, 62, 17)) + + consume2: (arg2) => {}, +>consume2 : Symbol(consume2, Decl(intraExpressionInferencesInContextSensitive1.ts, 62, 30)) +>arg2 : Symbol(arg2, Decl(intraExpressionInferencesInContextSensitive1.ts, 63, 17)) + + }); + }, +})); + diff --git a/tests/baselines/reference/intraExpressionInferencesInContextSensitive1.types b/tests/baselines/reference/intraExpressionInferencesInContextSensitive1.types index 1903b5f3f8593..5e5add9eab0d3 100644 --- a/tests/baselines/reference/intraExpressionInferencesInContextSensitive1.types +++ b/tests/baselines/reference/intraExpressionInferencesInContextSensitive1.types @@ -180,3 +180,174 @@ const stepResult = step((_something) => ({ }, })); +type Fn1 = (anything: unknown) => { +>Fn1 : Fn1 +> : ^^^^^^^^^^ +>anything : unknown +> : ^^^^^^^ + + produce: (arg: number) => T; +>produce : (arg: number) => T +> : ^ ^^ ^^^^^ +>arg : number +> : ^^^^^^ + + consume: (arg: T) => (anything: unknown) => { +>consume : (arg: T) => (anything: unknown) => { produce2: (arg: number) => T2; consume2: (arg: T2) => void; } +> : ^ ^^ ^^^^^ +>arg : T +> : ^ +>anything : unknown +> : ^^^^^^^ + + produce2: (arg: number) => T2; +>produce2 : (arg: number) => T2 +> : ^ ^^ ^^^^^ +>arg : number +> : ^^^^^^ + + consume2: (arg: T2) => void; +>consume2 : (arg: T2) => void +> : ^ ^^ ^^^^^ +>arg : T2 +> : ^^ + + }; +}; + +declare function test1(fn: Fn1): [T, T2]; +>test1 : (fn: Fn1) => [T, T2] +> : ^ ^^ ^^ ^^ ^^^^^ +>fn : Fn1 +> : ^^^^^^^^^^ + +const res1 = test1((_something) => ({ +>res1 : [string, number] +> : ^^^^^^^^^^^^^^^^ +>test1((_something) => ({ produce: (input) => "foo", consume: (arg) => { return (_something) => ({ produce2: (input) => 42, consume2: (arg2) => {}, }); },})) : [string, number] +> : ^^^^^^^^^^^^^^^^ +>test1 : (fn: Fn1) => [T, T2] +> : ^ ^^ ^^ ^^ ^^^^^ +>(_something) => ({ produce: (input) => "foo", consume: (arg) => { return (_something) => ({ produce2: (input) => 42, consume2: (arg2) => {}, }); },}) : (_something: unknown) => { produce: (input: number) => string; consume: (arg: string) => (_something: unknown) => { produce2: (input: number) => number; consume2: (arg2: number) => void; }; } +> : ^ ^^^^^^^^^^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^ +>_something : unknown +> : ^^^^^^^ +>({ produce: (input) => "foo", consume: (arg) => { return (_something) => ({ produce2: (input) => 42, consume2: (arg2) => {}, }); },}) : { produce: (input: number) => string; consume: (arg: string) => (_something: unknown) => { produce2: (input: number) => number; consume2: (arg2: number) => void; }; } +> : ^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^ +>{ produce: (input) => "foo", consume: (arg) => { return (_something) => ({ produce2: (input) => 42, consume2: (arg2) => {}, }); },} : { produce: (input: number) => string; consume: (arg: string) => (_something: unknown) => { produce2: (input: number) => number; consume2: (arg2: number) => void; }; } +> : ^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^ + + produce: (input) => "foo", +>produce : (input: number) => string +> : ^ ^^^^^^^^^^^^^^^^^^^ +>(input) => "foo" : (input: number) => string +> : ^ ^^^^^^^^^^^^^^^^^^^ +>input : number +> : ^^^^^^ +>"foo" : "foo" +> : ^^^^^ + + consume: (arg) => { +>consume : (arg: string) => (_something: unknown) => { produce2: (input: number) => number; consume2: (arg2: number) => void; } +> : ^ ^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^ +>(arg) => { return (_something) => ({ produce2: (input) => 42, consume2: (arg2) => {}, }); } : (arg: string) => (_something: unknown) => { produce2: (input: number) => number; consume2: (arg2: number) => void; } +> : ^ ^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^ +>arg : string +> : ^^^^^^ + + return (_something) => ({ +>(_something) => ({ produce2: (input) => 42, consume2: (arg2) => {}, }) : (_something: unknown) => { produce2: (input: number) => number; consume2: (arg2: number) => void; } +> : ^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^ +>_something : unknown +> : ^^^^^^^ +>({ produce2: (input) => 42, consume2: (arg2) => {}, }) : { produce2: (input: number) => number; consume2: (arg2: number) => void; } +> : ^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^ +>{ produce2: (input) => 42, consume2: (arg2) => {}, } : { produce2: (input: number) => number; consume2: (arg2: number) => void; } +> : ^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^ + + produce2: (input) => 42, +>produce2 : (input: number) => number +> : ^ ^^^^^^^^^^^^^^^^^^^ +>(input) => 42 : (input: number) => number +> : ^ ^^^^^^^^^^^^^^^^^^^ +>input : number +> : ^^^^^^ +>42 : 42 +> : ^^ + + consume2: (arg2) => {}, +>consume2 : (arg2: number) => void +> : ^ ^^^^^^^^^^^^^^^^^ +>(arg2) => {} : (arg2: number) => void +> : ^ ^^^^^^^^^^^^^^^^^ +>arg2 : number +> : ^^^^^^ + + }); + }, +})); + +const res2 = test1((_something) => ({ +>res2 : [string, number] +> : ^^^^^^^^^^^^^^^^ +>test1((_something) => ({ produce: (input) => "foo", consume: (arg) => { return () => ({ produce2: (input) => 42, consume2: (arg2) => {}, }); },})) : [string, number] +> : ^^^^^^^^^^^^^^^^ +>test1 : (fn: Fn1) => [T, T2] +> : ^ ^^ ^^ ^^ ^^^^^ +>(_something) => ({ produce: (input) => "foo", consume: (arg) => { return () => ({ produce2: (input) => 42, consume2: (arg2) => {}, }); },}) : (_something: unknown) => { produce: (input: number) => string; consume: (arg: string) => () => { produce2: (input: number) => number; consume2: (arg2: number) => void; }; } +> : ^ ^^^^^^^^^^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^ +>_something : unknown +> : ^^^^^^^ +>({ produce: (input) => "foo", consume: (arg) => { return () => ({ produce2: (input) => 42, consume2: (arg2) => {}, }); },}) : { produce: (input: number) => string; consume: (arg: string) => () => { produce2: (input: number) => number; consume2: (arg2: number) => void; }; } +> : ^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^ +>{ produce: (input) => "foo", consume: (arg) => { return () => ({ produce2: (input) => 42, consume2: (arg2) => {}, }); },} : { produce: (input: number) => string; consume: (arg: string) => () => { produce2: (input: number) => number; consume2: (arg2: number) => void; }; } +> : ^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^ + + produce: (input) => "foo", +>produce : (input: number) => string +> : ^ ^^^^^^^^^^^^^^^^^^^ +>(input) => "foo" : (input: number) => string +> : ^ ^^^^^^^^^^^^^^^^^^^ +>input : number +> : ^^^^^^ +>"foo" : "foo" +> : ^^^^^ + + consume: (arg) => { +>consume : (arg: string) => () => { produce2: (input: number) => number; consume2: (arg2: number) => void; } +> : ^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^ +>(arg) => { return () => ({ produce2: (input) => 42, consume2: (arg2) => {}, }); } : (arg: string) => () => { produce2: (input: number) => number; consume2: (arg2: number) => void; } +> : ^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^ +>arg : string +> : ^^^^^^ + + return () => ({ +>() => ({ produce2: (input) => 42, consume2: (arg2) => {}, }) : () => { produce2: (input: number) => number; consume2: (arg2: number) => void; } +> : ^^^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^ +>({ produce2: (input) => 42, consume2: (arg2) => {}, }) : { produce2: (input: number) => number; consume2: (arg2: number) => void; } +> : ^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^ +>{ produce2: (input) => 42, consume2: (arg2) => {}, } : { produce2: (input: number) => number; consume2: (arg2: number) => void; } +> : ^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^ + + produce2: (input) => 42, +>produce2 : (input: number) => number +> : ^ ^^^^^^^^^^^^^^^^^^^ +>(input) => 42 : (input: number) => number +> : ^ ^^^^^^^^^^^^^^^^^^^ +>input : number +> : ^^^^^^ +>42 : 42 +> : ^^ + + consume2: (arg2) => {}, +>consume2 : (arg2: number) => void +> : ^ ^^^^^^^^^^^^^^^^^ +>(arg2) => {} : (arg2: number) => void +> : ^ ^^^^^^^^^^^^^^^^^ +>arg2 : number +> : ^^^^^^ + + }); + }, +})); + diff --git a/tests/cases/conformance/types/typeRelationships/typeInference/InferFromReturnsInContextSensitive1.ts b/tests/cases/conformance/types/typeRelationships/typeInference/InferFromReturnsInContextSensitive1.ts index 0a76276f58b4f..019f7056858d2 100644 --- a/tests/cases/conformance/types/typeRelationships/typeInference/InferFromReturnsInContextSensitive1.ts +++ b/tests/cases/conformance/types/typeRelationships/typeInference/InferFromReturnsInContextSensitive1.ts @@ -17,6 +17,11 @@ create((arg) => ({ onEnd: (context) => {}, })); +create((arg) => ({ + onEnd: (context) => {}, + onStart: () => ({ time: new Date() }), +})); + // https://github.com/microsoft/TypeScript/issues/57021 type Schema = Record; @@ -26,13 +31,13 @@ type StepFunction = (anything: unknown) => { readonly toAnswers?: (keys: keyof TSchema) => unknown; }; -function step1( +function step( stepVal: StepFunction, ): StepFunction { return stepVal; } -const stepResult1 = step1((_something) => ({ +const stepResult1 = step((_something) => ({ schema: { attribute: "anything", }, @@ -42,3 +47,104 @@ const stepResult1 = step1((_something) => ({ return { test }; }, })); + +const stepResult2 = step((_something) => ({ + toAnswers: (keys) => { + type Test = string extends typeof keys ? never : "true"; + const test: Test = "true"; // ok + return { test }; + }, + schema: { + attribute: "anything", + }, +})); + +type Fn1 = (anything: unknown) => { + stuff: T; + consume: (arg: T) => (anything: unknown) => { + stuff2: T2; + consume2: (arg: T2) => void; + }; +}; + +declare function test1(fn: Fn1): [T, T2]; + +const res1 = test1((_something) => ({ + stuff: "foo", + consume: (arg) => { + return (_something) => ({ + stuff2: 42, + consume2: (arg2) => {}, + }); + }, +})); + +const res2 = test1((_something) => ({ + consume: (arg) => { + return (_something) => ({ + consume2: (arg2) => {}, + stuff2: 42, + }); + }, + stuff: "foo", +})); + +const res3 = test1((_something) => ({ + stuff: "foo", + consume: () => { + return (_something) => ({ + stuff2: 42, + consume2: (arg2) => {}, + }); + }, +})); + +const res4 = test1((_something) => ({ + consume: () => { + return (_something) => ({ + consume2: (arg2) => {}, + stuff2: 42, + }); + }, + stuff: "foo", +})); + +const res5 = test1((_something) => ({ + stuff: "foo", + consume: () => { + return () => ({ + stuff2: 42, + consume2: (arg2) => {}, + }); + }, +})); + +const res6 = test1((_something) => ({ + consume: () => { + return () => ({ + consume2: (arg2) => {}, + stuff2: 42, + }); + }, + stuff: "foo", +})); + +const res7 = test1((_something) => ({ + stuff: "foo", + consume: () => { + return () => ({ + stuff2: 42, + consume2: () => {}, + }); + }, +})); + +const res8 = test1((_something) => ({ + consume: () => { + return () => ({ + consume2: () => {}, + stuff2: 42, + }); + }, + stuff: "foo", +})); diff --git a/tests/cases/conformance/types/typeRelationships/typeInference/intraExpressionInferencesInContextSensitive1.ts b/tests/cases/conformance/types/typeRelationships/typeInference/intraExpressionInferencesInContextSensitive1.ts index 927d7fd989499..21a4631c1ae62 100644 --- a/tests/cases/conformance/types/typeRelationships/typeInference/intraExpressionInferencesInContextSensitive1.ts +++ b/tests/cases/conformance/types/typeRelationships/typeInference/intraExpressionInferencesInContextSensitive1.ts @@ -38,3 +38,33 @@ const stepResult = step((_something) => ({ return { test }; }, })); + +type Fn1 = (anything: unknown) => { + produce: (arg: number) => T; + consume: (arg: T) => (anything: unknown) => { + produce2: (arg: number) => T2; + consume2: (arg: T2) => void; + }; +}; + +declare function test1(fn: Fn1): [T, T2]; + +const res1 = test1((_something) => ({ + produce: (input) => "foo", + consume: (arg) => { + return (_something) => ({ + produce2: (input) => 42, + consume2: (arg2) => {}, + }); + }, +})); + +const res2 = test1((_something) => ({ + produce: (input) => "foo", + consume: (arg) => { + return () => ({ + produce2: (input) => 42, + consume2: (arg2) => {}, + }); + }, +}));