diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 80b61edd3657a..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 */ @@ -38938,7 +38941,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)) { @@ -38952,11 +38955,12 @@ 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; - if (checkMode && checkMode & CheckMode.Inferential) { + if (checkMode & CheckMode.Inferential) { inferFromAnnotatedParameters(signature, contextualSignature, inferenceContext!); const restType = getEffectiveRestType(contextualSignature); if (restType && restType.flags & TypeFlags.TypeParameter) { @@ -38974,15 +38978,34 @@ 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); - if (!signature.resolvedReturnType) { - signature.resolvedReturnType = returnType; + let contextualReturnType: Type; + let returnType: Type; + + 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)); + inferTypes(inferenceContext!.inferences, returnType, contextualReturnType); + if (isReturnContextSensitive) { + returnType = getReturnTypeFromBody(node, checkMode); + } + } + else { + returnType = getReturnTypeFromBody(node, checkMode); } + signature.resolvedReturnType ??= returnType; } checkSignatureDeclaration(node); } diff --git a/tests/baselines/reference/InferFromReturnsInContextSensitive1.js b/tests/baselines/reference/InferFromReturnsInContextSensitive1.js new file mode 100644 index 0000000000000..177dc45641039 --- /dev/null +++ b/tests/baselines/reference/InferFromReturnsInContextSensitive1.js @@ -0,0 +1,295 @@ +//// [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) => {}, +})); + +create((arg) => ({ + onEnd: (context) => {}, + onStart: () => ({ time: new Date() }), +})); + +// https://github.com/microsoft/TypeScript/issues/57021 + +type Schema = Record; + +type StepFunction = (anything: unknown) => { + readonly schema: TSchema; + readonly toAnswers?: (keys: keyof TSchema) => unknown; +}; + +function step( + stepVal: StepFunction, +): StepFunction { + return stepVal; +} + +const stepResult1 = step((_something) => ({ + schema: { + attribute: "anything", + }, + toAnswers: (keys) => { + type Test = string extends typeof keys ? never : "true"; + const test: Test = "true"; // ok + 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] +"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 (arg) { return ({ + onEnd: function (context) { }, + onStart: function () { return ({ time: new Date() }); }, +}); }); +function step(stepVal) { + return stepVal; +} +var stepResult1 = step(function (_something) { return ({ + schema: { + attribute: "anything", + }, + toAnswers: function (keys) { + var test = "true"; // ok + 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] +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 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 new file mode 100644 index 0000000000000..2b87289576f5b --- /dev/null +++ b/tests/baselines/reference/InferFromReturnsInContextSensitive1.symbols @@ -0,0 +1,396 @@ +//// [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)) + +})); + +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, 19, 4)) +>Record : Symbol(Record, Decl(lib.es5.d.ts, --, --)) + +type StepFunction = (anything: unknown) => { +>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, 25, 77)) +>TSchema : Symbol(TSchema, Decl(InferFromReturnsInContextSensitive1.ts, 25, 18)) + + readonly toAnswers?: (keys: keyof TSchema) => unknown; +>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 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, 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, 23, 38)) +>TSchema : Symbol(TSchema, Decl(InferFromReturnsInContextSensitive1.ts, 30, 14)) + + return stepVal; +>stepVal : Symbol(stepVal, Decl(InferFromReturnsInContextSensitive1.ts, 30, 47)) +} + +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, 36, 43)) + + attribute: "anything", +>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, 47, 43)) +>keys : Symbol(keys, Decl(InferFromReturnsInContextSensitive1.ts, 48, 14)) + + type Test = string extends typeof keys ? never : "true"; +>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, 50, 9)) +>Test : Symbol(Test, Decl(InferFromReturnsInContextSensitive1.ts, 48, 24)) + + return { test }; +>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 new file mode 100644 index 0000000000000..c3fe947d1e083 --- /dev/null +++ b/tests/baselines/reference/InferFromReturnsInContextSensitive1.types @@ -0,0 +1,749 @@ +//// [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; } +> : ^^^^^^^^^^^^^^^ + +})); + +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; +>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 step( +>step : (stepVal: StepFunction) => StepFunction +> : ^ ^^^^^^^^^ ^^^^^^^^^^^ ^^ ^^^^^ + + stepVal: StepFunction, +>stepVal : StepFunction +> : ^^^^^^^^^^^^^^^^^^^^^ + +): StepFunction { + return stepVal; +>stepVal : StepFunction +> : ^^^^^^^^^^^^^^^^^^^^^ +} + +const stepResult1 = step((_something) => ({ +>stepResult1 : StepFunction<{ attribute: string; }> +> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +>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 +> : ^^^^^^^ +>({ 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" +> : ^^^^^^ + + }, +})); + +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/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/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/baselines/reference/intraExpressionInferencesInContextSensitive1.js b/tests/baselines/reference/intraExpressionInferencesInContextSensitive1.js new file mode 100644 index 0000000000000..3da93cbc3d46b --- /dev/null +++ b/tests/baselines/reference/intraExpressionInferencesInContextSensitive1.js @@ -0,0 +1,138 @@ +//// [tests/cases/conformance/types/typeRelationships/typeInference/intraExpressionInferencesInContextSensitive1.ts] //// + +//// [intraExpressionInferencesInContextSensitive1.ts] +type Options = { + onStart?: (arg: number) => TContext; + onEnd?: (context: TContext) => void; +}; + +function create(builder: (arg: boolean) => Options) { + return builder(true); +} + +create((arg) => ({ + onStart: (arg) => ({ time: new Date() }), + onEnd: (context) => {}, +})); + +type Schema = Record; + +type StepFunction = (anything: unknown) => { + readonly schema: (thing: number) => TSchema; + readonly toAnswers?: (keys: keyof TSchema) => unknown; +}; + +function step( + stepVal: StepFunction, +): StepFunction { + return stepVal; +} + +const stepResult = step((_something) => ({ + schema: (thing) => ({ + attribute: "anything", + }), + toAnswers: (keys) => { + type Test = string extends typeof keys ? never : "true"; + const test: Test = "true"; // ok + 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] +"use strict"; +function create(builder) { + return builder(true); +} +create(function (arg) { return ({ + onStart: function (arg) { return ({ time: new Date() }); }, + onEnd: function (context) { }, +}); }); +function step(stepVal) { + return stepVal; +} +var stepResult = step(function (_something) { return ({ + schema: function (thing) { return ({ + attribute: "anything", + }); }, + toAnswers: function (keys) { + var test = "true"; // ok + 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] +type Options = { + 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: (thing: number) => TSchema; + readonly toAnswers?: (keys: keyof TSchema) => unknown; +}; +declare function step(stepVal: StepFunction): StepFunction; +declare const stepResult: StepFunction<{ + attribute: string; +}>; +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 new file mode 100644 index 0000000000000..1452767c32b22 --- /dev/null +++ b/tests/baselines/reference/intraExpressionInferencesInContextSensitive1.symbols @@ -0,0 +1,215 @@ +//// [tests/cases/conformance/types/typeRelationships/typeInference/intraExpressionInferencesInContextSensitive1.ts] //// + +=== intraExpressionInferencesInContextSensitive1.ts === +type Options = { +>Options : Symbol(Options, Decl(intraExpressionInferencesInContextSensitive1.ts, 0, 0)) +>TContext : Symbol(TContext, Decl(intraExpressionInferencesInContextSensitive1.ts, 0, 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, 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, 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, 5, 16)) + + return builder(true); +>builder : Symbol(builder, Decl(intraExpressionInferencesInContextSensitive1.ts, 5, 26)) +} + +create((arg) => ({ +>create : Symbol(create, Decl(intraExpressionInferencesInContextSensitive1.ts, 3, 2)) +>arg : Symbol(arg, Decl(intraExpressionInferencesInContextSensitive1.ts, 9, 8)) + + 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, 10, 43)) +>context : Symbol(context, Decl(intraExpressionInferencesInContextSensitive1.ts, 11, 10)) + +})); + +type Schema = Record; +>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, 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: (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, 17, 46)) +>keys : Symbol(keys, Decl(intraExpressionInferencesInContextSensitive1.ts, 18, 24)) +>TSchema : Symbol(TSchema, Decl(intraExpressionInferencesInContextSensitive1.ts, 16, 18)) + +}; + +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, 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, 14, 38)) +>TSchema : Symbol(TSchema, Decl(intraExpressionInferencesInContextSensitive1.ts, 21, 14)) + + return stepVal; +>stepVal : Symbol(stepVal, Decl(intraExpressionInferencesInContextSensitive1.ts, 21, 47)) +} + +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, 27, 42)) +>thing : Symbol(thing, Decl(intraExpressionInferencesInContextSensitive1.ts, 28, 11)) + + attribute: "anything", +>attribute : Symbol(attribute, Decl(intraExpressionInferencesInContextSensitive1.ts, 28, 23)) + + }), + toAnswers: (keys) => { +>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, 31, 24)) +>keys : Symbol(keys, Decl(intraExpressionInferencesInContextSensitive1.ts, 31, 14)) + + const test: Test = "true"; // ok +>test : Symbol(test, Decl(intraExpressionInferencesInContextSensitive1.ts, 33, 9)) +>Test : Symbol(Test, Decl(intraExpressionInferencesInContextSensitive1.ts, 31, 24)) + + return { test }; +>test : Symbol(test, Decl(intraExpressionInferencesInContextSensitive1.ts, 34, 12)) + + }, +})); + +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 new file mode 100644 index 0000000000000..5e5add9eab0d3 --- /dev/null +++ b/tests/baselines/reference/intraExpressionInferencesInContextSensitive1.types @@ -0,0 +1,353 @@ +//// [tests/cases/conformance/types/typeRelationships/typeInference/intraExpressionInferencesInContextSensitive1.ts] //// + +=== intraExpressionInferencesInContextSensitive1.ts === +type Options = { +>Options : Options +> : ^^^^^^^^^^^^^^^^^ + + onStart?: (arg: number) => TContext; +>onStart : ((arg: number) => TContext) | undefined +> : ^^ ^^ ^^^^^ ^^^^^^^^^^^^^ +>arg : number +> : ^^^^^^ + + 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: (arg) => ({ time: new Date() }), onEnd: (context) => {},})) : Options<{ time: Date; }> +> : ^^^^^^^^^^^^^^^^^^^^^^^^ +>create : (builder: (arg: boolean) => Options) => Options +> : ^ ^^ ^^ ^^^^^^^^^^^^^^^^^^^^^^ +>(arg) => ({ onStart: (arg) => ({ time: new Date() }), onEnd: (context) => {},}) : (arg: boolean) => { onStart: (arg: number) => { time: Date; }; onEnd: (context: { time: Date; }) => void; } +> : ^ ^^^^^^^^^^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +>arg : boolean +> : ^^^^^^^ +>({ 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; } +> : ^^^^^^^^^^^^^^^ +>time : Date +> : ^^^^ +>new Date() : Date +> : ^^^^ +>Date : DateConstructor +> : ^^^^^^^^^^^^^^^ + + onEnd: (context) => {}, +>onEnd : (context: { time: Date; }) => void +> : ^ ^^^^^^^^^^^^^^^^^^^^^^^^^^ +>(context) => {} : (context: { time: Date; }) => void +> : ^ ^^^^^^^^^^^^^^^^^^^^^^^^^^ +>context : { time: Date; } +> : ^^^^^^^^^^^^^^^ + +})); + +type Schema = Record; +>Schema : Schema +> : ^^^^^^ + +type StepFunction = (anything: unknown) => { +>StepFunction : StepFunction +> : ^^^^^^^^^^^^^^^^^^^^^ +>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 step( +>step : (stepVal: StepFunction) => StepFunction +> : ^ ^^^^^^^^^ ^^^^^^^^^^^ ^^ ^^^^^ + + stepVal: StepFunction, +>stepVal : StepFunction +> : ^^^^^^^^^^^^^^^^^^^^^ + +): StepFunction { + return stepVal; +>stepVal : StepFunction +> : ^^^^^^^^^^^^^^^^^^^^^ +} + +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 +> : ^^^^^^^ +>({ 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" +> : ^^^^^^ + + }, +})); + +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/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), +); 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 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..019f7056858d2 --- /dev/null +++ b/tests/cases/conformance/types/typeRelationships/typeInference/InferFromReturnsInContextSensitive1.ts @@ -0,0 +1,150 @@ +// @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) => {}, +})); + +create((arg) => ({ + onEnd: (context) => {}, + onStart: () => ({ time: new Date() }), +})); + +// https://github.com/microsoft/TypeScript/issues/57021 + +type Schema = Record; + +type StepFunction = (anything: unknown) => { + readonly schema: TSchema; + readonly toAnswers?: (keys: keyof TSchema) => unknown; +}; + +function step( + stepVal: StepFunction, +): StepFunction { + return stepVal; +} + +const stepResult1 = step((_something) => ({ + schema: { + attribute: "anything", + }, + toAnswers: (keys) => { + type Test = string extends typeof keys ? never : "true"; + const test: Test = "true"; // ok + 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 new file mode 100644 index 0000000000000..21a4631c1ae62 --- /dev/null +++ b/tests/cases/conformance/types/typeRelationships/typeInference/intraExpressionInferencesInContextSensitive1.ts @@ -0,0 +1,70 @@ +// @strict: true +// @declaration: true + +type Options = { + onStart?: (arg: number) => TContext; + onEnd?: (context: TContext) => void; +}; + +function create(builder: (arg: boolean) => Options) { + return builder(true); +} + +create((arg) => ({ + onStart: (arg) => ({ time: new Date() }), + onEnd: (context) => {}, +})); + +type Schema = Record; + +type StepFunction = (anything: unknown) => { + readonly schema: (thing: number) => TSchema; + readonly toAnswers?: (keys: keyof TSchema) => unknown; +}; + +function step( + stepVal: StepFunction, +): StepFunction { + return stepVal; +} + +const stepResult = step((_something) => ({ + schema: (thing) => ({ + attribute: "anything", + }), + toAnswers: (keys) => { + type Test = string extends typeof keys ? never : "true"; + const test: Test = "true"; // ok + 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) => {}, + }); + }, +}));