From bcb0da5dc4eb43369b47e20d48929c82fac52aaf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mateusz=20Burzy=C5=84ski?= Date: Mon, 8 May 2023 09:25:32 +0200 Subject: [PATCH 1/3] Add nested call and new expressions as potential intra expression inference sites --- src/compiler/checker.ts | 63 ++++++++------- src/compiler/types.ts | 2 +- src/services/refactors/extractSymbol.ts | 2 +- .../intraExpressionInferences.errors.txt | 24 +++++- .../reference/intraExpressionInferences.js | 47 ++++++++++- .../intraExpressionInferences.symbols | 79 +++++++++++++++++++ .../reference/intraExpressionInferences.types | 75 ++++++++++++++++++ .../intraExpressionInferencesJsx.symbols | 45 +++++++++++ .../intraExpressionInferencesJsx.types | 41 ++++++++++ .../intraExpressionInferences.ts | 23 ++++++ .../intraExpressionInferencesJsx.tsx | 13 +++ 11 files changed, 383 insertions(+), 31 deletions(-) diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 98cd87923761e..6e620b3e67e99 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -1652,7 +1652,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { const node = getParseTreeNode(nodeIn, isJsxAttributeLike); return node && getContextualTypeForJsxAttribute(node, /*contextFlags*/ undefined); }, - isContextSensitive, + containsContextSensitive, getTypeOfPropertyOfContextualType, getFullyQualifiedName, getResolvedSignature: (node, candidatesOutArray, argumentCount) => @@ -6253,7 +6253,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { } function symbolValueDeclarationIsContextSensitive(symbol: Symbol): boolean { - return symbol && !!symbol.valueDeclaration && isExpression(symbol.valueDeclaration) && !isContextSensitive(symbol.valueDeclaration); + return symbol && !!symbol.valueDeclaration && isExpression(symbol.valueDeclaration) && !containsContextSensitive(symbol.valueDeclaration); } function toNodeBuilderFlags(flags = TypeFormatFlags.None): NodeBuilderFlags { @@ -19165,47 +19165,56 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { return createIndexInfo(info.keyType, instantiateType(info.type, mapper), info.isReadonly, info.declaration); } - // Returns true if the given expression contains (at any level of nesting) a function or arrow expression - // that is subject to contextual typing. - function isContextSensitive(node: Expression | MethodDeclaration | ObjectLiteralElementLike | JsxAttributeLike | JsxChild): boolean { + function containsContextRelatedNode(node: Expression | MethodDeclaration | ObjectLiteralElementLike | JsxAttributeLike | JsxChild, predicate: (node: Node) => boolean): boolean { Debug.assert(node.kind !== SyntaxKind.MethodDeclaration || isObjectLiteralMethod(node)); switch (node.kind) { case SyntaxKind.FunctionExpression: case SyntaxKind.ArrowFunction: case SyntaxKind.MethodDeclaration: - case SyntaxKind.FunctionDeclaration: // Function declarations can have context when annotated with a jsdoc @type - return isContextSensitiveFunctionLikeDeclaration(node as FunctionExpression | ArrowFunction | MethodDeclaration); + case SyntaxKind.FunctionDeclaration: + case SyntaxKind.CallExpression: + case SyntaxKind.NewExpression: + return predicate(node); case SyntaxKind.ObjectLiteralExpression: - return some((node as ObjectLiteralExpression).properties, isContextSensitive); + return some((node as ObjectLiteralExpression).properties, p => containsContextRelatedNode(p, predicate)); case SyntaxKind.ArrayLiteralExpression: - return some((node as ArrayLiteralExpression).elements, isContextSensitive); + return some((node as ArrayLiteralExpression).elements, e => containsContextRelatedNode(e, predicate)); case SyntaxKind.ConditionalExpression: - return isContextSensitive((node as ConditionalExpression).whenTrue) || - isContextSensitive((node as ConditionalExpression).whenFalse); + return containsContextRelatedNode((node as ConditionalExpression).whenTrue, predicate) || + containsContextRelatedNode((node as ConditionalExpression).whenFalse, predicate); case SyntaxKind.BinaryExpression: return ((node as BinaryExpression).operatorToken.kind === SyntaxKind.BarBarToken || (node as BinaryExpression).operatorToken.kind === SyntaxKind.QuestionQuestionToken) && - (isContextSensitive((node as BinaryExpression).left) || isContextSensitive((node as BinaryExpression).right)); + (containsContextRelatedNode((node as BinaryExpression).left, predicate) || containsContextRelatedNode((node as BinaryExpression).right, predicate)); case SyntaxKind.PropertyAssignment: - return isContextSensitive((node as PropertyAssignment).initializer); + return containsContextRelatedNode((node as PropertyAssignment).initializer, predicate); case SyntaxKind.ParenthesizedExpression: - return isContextSensitive((node as ParenthesizedExpression).expression); + return containsContextRelatedNode((node as ParenthesizedExpression).expression, predicate); case SyntaxKind.JsxAttributes: - return some((node as JsxAttributes).properties, isContextSensitive) || isJsxOpeningElement(node.parent) && some(node.parent.parent.children, isContextSensitive); + return some((node as JsxAttributes).properties, p => containsContextRelatedNode(p, predicate)) || isJsxOpeningElement(node.parent) && some(node.parent.parent.children, c => containsContextRelatedNode(c, predicate)); case SyntaxKind.JsxAttribute: { - // If there is no initializer, JSX attribute has a boolean value of true which is not context sensitive. const { initializer } = node as JsxAttribute; - return !!initializer && isContextSensitive(initializer); + return !!initializer && containsContextRelatedNode(initializer, predicate); } case SyntaxKind.JsxExpression: { // It is possible to that node.expression is undefined (e.g
) const { expression } = node as JsxExpression; - return !!expression && isContextSensitive(expression); + return !!expression && containsContextRelatedNode(expression, predicate); } } return false; } + // Returns true if the given expression contains (at any level of nesting) a function or arrow expression + // that is subject to contextual typing. + function containsContextSensitive(node: Expression | MethodDeclaration | ObjectLiteralElementLike | JsxAttributeLike | JsxChild): boolean { + return containsContextRelatedNode(node, isContextSensitiveFunctionOrObjectLiteralMethod); + } + + function containsContextSensitiveOrCallOrNewExpression(node: Expression | MethodDeclaration | ObjectLiteralElementLike | JsxAttributeLike | JsxChild): boolean { + return containsContextRelatedNode(node, n => isContextSensitiveFunctionOrObjectLiteralMethod(n) || isCallOrNewExpression(n)); + } + function isContextSensitiveFunctionLikeDeclaration(node: FunctionLikeDeclaration): boolean { return hasContextSensitiveParameters(node) || hasContextSensitiveReturnExpression(node); } @@ -19215,9 +19224,9 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { return false; } if (node.body.kind !== SyntaxKind.Block) { - return isContextSensitive(node.body); + return containsContextSensitive(node.body); } - return !!forEachReturnStatement(node.body as Block, (statement) => !!statement.expression && isContextSensitive(statement.expression)); + return !!forEachReturnStatement(node.body as Block, (statement) => !!statement.expression && containsContextSensitive(statement.expression)); } function isContextSensitiveFunctionOrObjectLiteralMethod(func: Node): func is FunctionExpression | ArrowFunction | MethodDeclaration { @@ -29983,7 +29992,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { const type = checkExpressionForMutableLocation(e, checkMode, forceTuple); elementTypes.push(addOptionality(type, /*isProperty*/ true, hasOmittedExpression)); elementFlags.push(hasOmittedExpression ? ElementFlags.Optional : ElementFlags.Required); - if (inTupleContext && checkMode && checkMode & CheckMode.Inferential && !(checkMode & CheckMode.SkipContextSensitive) && isContextSensitive(e)) { + if (inTupleContext && checkMode && checkMode & CheckMode.Inferential && !(checkMode & CheckMode.SkipContextSensitive) && containsContextSensitiveOrCallOrNewExpression(e)) { const inferenceContext = getInferenceContext(node); Debug.assert(inferenceContext); // In CheckMode.Inferential we should always have an inference context addIntraExpressionInferenceSite(inferenceContext, e, type); @@ -30208,8 +30217,8 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { member = prop; allPropertiesTable?.set(prop.escapedName, prop); - if (contextualType && checkMode && checkMode & CheckMode.Inferential && !(checkMode & CheckMode.SkipContextSensitive) && - (memberDecl.kind === SyntaxKind.PropertyAssignment || memberDecl.kind === SyntaxKind.MethodDeclaration) && isContextSensitive(memberDecl)) { + if (contextualType && checkMode && checkMode & CheckMode.Inferential && (!(checkMode & CheckMode.SkipContextSensitive) && + (memberDecl.kind === SyntaxKind.PropertyAssignment || memberDecl.kind === SyntaxKind.MethodDeclaration) && containsContextSensitiveOrCallOrNewExpression(memberDecl))) { const inferenceContext = getInferenceContext(node); Debug.assert(inferenceContext); // In CheckMode.Inferential we should always have an inference context const inferenceNode = memberDecl.kind === SyntaxKind.PropertyAssignment ? memberDecl.initializer : memberDecl; @@ -30465,7 +30474,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { addDeprecatedSuggestion(attributeDecl.name, prop.declarations, attributeDecl.name.escapedText as string); } } - if (contextualType && checkMode && checkMode & CheckMode.Inferential && !(checkMode & CheckMode.SkipContextSensitive) && isContextSensitive(attributeDecl)) { + if (contextualType && checkMode && checkMode & CheckMode.Inferential && !(checkMode & CheckMode.SkipContextSensitive) && containsContextSensitiveOrCallOrNewExpression(attributeDecl)) { const inferenceContext = getInferenceContext(attributes); Debug.assert(inferenceContext); // In CheckMode.Inferential we should always have an inference context const inferenceNode = (attributeDecl.initializer as JsxExpression).expression!; @@ -33138,7 +33147,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { // For a decorator, no arguments are susceptible to contextual typing due to the fact // decorators are applied to a declaration by the emitter, and not to an expression. const isSingleNonGenericCandidate = candidates.length === 1 && !candidates[0].typeParameters; - let argCheckMode = !isDecorator && !isSingleNonGenericCandidate && some(args, isContextSensitive) ? CheckMode.SkipContextSensitive : CheckMode.Normal; + let argCheckMode = !isDecorator && !isSingleNonGenericCandidate && some(args, containsContextSensitive) ? CheckMode.SkipContextSensitive : CheckMode.Normal; argCheckMode |= checkMode & CheckMode.IsForStringLiteralArgumentCompletions; // The following variables are captured and modified by calls to chooseOverload. @@ -35865,7 +35874,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { } // The identityMapper object is used to indicate that function expressions are wildcards - if (checkMode && checkMode & CheckMode.SkipContextSensitive && isContextSensitive(node)) { + if (checkMode && checkMode & CheckMode.SkipContextSensitive && containsContextSensitive(node)) { // Skip parameters, return signature with return type that retains noncontextual parts so inferences can still be drawn in an early stage if (!getEffectiveReturnTypeNode(node) && !hasContextSensitiveParameters(node)) { // Return plain anyFunctionType if there is no possibility we'll make inferences from the return type @@ -35910,7 +35919,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { if (!signature) { return; } - if (isContextSensitive(node)) { + if (containsContextSensitive(node)) { if (contextualSignature) { const inferenceContext = getInferenceContext(node); let instantiatedContextualSignature: Signature | undefined; diff --git a/src/compiler/types.ts b/src/compiler/types.ts index c97bbaffa2834..8b8ae32bc32ed 100644 --- a/src/compiler/types.ts +++ b/src/compiler/types.ts @@ -5064,7 +5064,7 @@ export interface TypeChecker { /** @internal */ getContextualTypeForObjectLiteralElement(element: ObjectLiteralElementLike): Type | undefined; /** @internal */ getContextualTypeForArgumentAtIndex(call: CallLikeExpression, argIndex: number): Type | undefined; /** @internal */ getContextualTypeForJsxAttribute(attribute: JsxAttribute | JsxSpreadAttribute): Type | undefined; - /** @internal */ isContextSensitive(node: Expression | MethodDeclaration | ObjectLiteralElementLike | JsxAttributeLike): boolean; + /** @internal */ containsContextSensitive(node: Expression | MethodDeclaration | ObjectLiteralElementLike | JsxAttributeLike): boolean; /** @internal */ getTypeOfPropertyOfContextualType(type: Type, name: __String): Type | undefined; /** diff --git a/src/services/refactors/extractSymbol.ts b/src/services/refactors/extractSymbol.ts index 9efcce3006624..df4bee7129c1d 100644 --- a/src/services/refactors/extractSymbol.ts +++ b/src/services/refactors/extractSymbol.ts @@ -1357,7 +1357,7 @@ function extractConstantInScope( : getUniqueName(isClassLike(scope) ? "newProperty" : "newLocal", file); const isJS = isInJSFile(scope); - let variableType = isJS || !checker.isContextSensitive(node) + let variableType = isJS || !checker.containsContextSensitive(node) ? undefined : checker.typeToTypeNode(checker.getContextualType(node)!, scope, NodeBuilderFlags.NoTruncation); // TODO: GH#18217 diff --git a/tests/baselines/reference/intraExpressionInferences.errors.txt b/tests/baselines/reference/intraExpressionInferences.errors.txt index 745cd9b9e426c..52afcbaab4c1e 100644 --- a/tests/baselines/reference/intraExpressionInferences.errors.txt +++ b/tests/baselines/reference/intraExpressionInferences.errors.txt @@ -212,4 +212,26 @@ tests/cases/conformance/types/typeRelationships/typeInference/intraExpressionInf let test1: "a" = u } }) - \ No newline at end of file + + type ErrorFn = (error: unknown) => void; + + declare const genericFn: (args: { + parser: (p: unknown, errorFn: ErrorFn) => T; + handler: (data: { body: T }) => unknown; + }) => T; + + declare const createParser: (arg: T) => (p: unknown, errorFn: ErrorFn) => T; + + genericFn({ + parser: createParser(1 as const), + handler: ({ body: _ }) => {}, + }); + + declare const genericFnTuple: ( + args: [ + parser: (p: unknown, errorFn: ErrorFn) => T, + handler: (data: { body: T }) => unknown + ] + ) => T; + + genericFnTuple([createParser(1 as const), ({ body: _ }) => {}]); \ No newline at end of file diff --git a/tests/baselines/reference/intraExpressionInferences.js b/tests/baselines/reference/intraExpressionInferences.js index 5392616122e7b..21fb6512ac966 100644 --- a/tests/baselines/reference/intraExpressionInferences.js +++ b/tests/baselines/reference/intraExpressionInferences.js @@ -197,7 +197,29 @@ branch({ let test1: "a" = u } }) - + +type ErrorFn = (error: unknown) => void; + +declare const genericFn: (args: { + parser: (p: unknown, errorFn: ErrorFn) => T; + handler: (data: { body: T }) => unknown; +}) => T; + +declare const createParser: (arg: T) => (p: unknown, errorFn: ErrorFn) => T; + +genericFn({ + parser: createParser(1 as const), + handler: ({ body: _ }) => {}, +}); + +declare const genericFnTuple: ( + args: [ + parser: (p: unknown, errorFn: ErrorFn) => T, + handler: (data: { body: T }) => unknown + ] +) => T; + +genericFnTuple([createParser(1 as const), ({ body: _ }) => {}]); //// [intraExpressionInferences.js] "use strict"; @@ -316,6 +338,15 @@ branch({ var test1 = u; } }); +genericFn({ + parser: createParser(1), + handler: function (_b) { + var _ = _b.body; + }, +}); +genericFnTuple([createParser(1), function (_b) { + var _ = _b.body; + }]); //// [intraExpressionInferences.d.ts] @@ -383,3 +414,17 @@ declare const branch: (_: { then: (u: U) => void; }) => void; declare const x: "a" | "b"; +type ErrorFn = (error: unknown) => void; +declare const genericFn: (args: { + parser: (p: unknown, errorFn: ErrorFn) => T; + handler: (data: { + body: T; + }) => unknown; +}) => T; +declare const createParser: (arg: T) => (p: unknown, errorFn: ErrorFn) => T; +declare const genericFnTuple: (args: [ + parser: (p: unknown, errorFn: ErrorFn) => T, + handler: (data: { + body: T; + }) => unknown +]) => T; diff --git a/tests/baselines/reference/intraExpressionInferences.symbols b/tests/baselines/reference/intraExpressionInferences.symbols index 6651221146f12..8c2aa13f82aca 100644 --- a/tests/baselines/reference/intraExpressionInferences.symbols +++ b/tests/baselines/reference/intraExpressionInferences.symbols @@ -626,3 +626,82 @@ branch({ } }) +type ErrorFn = (error: unknown) => void; +>ErrorFn : Symbol(ErrorFn, Decl(intraExpressionInferences.ts, 197, 2)) +>error : Symbol(error, Decl(intraExpressionInferences.ts, 199, 16)) + +declare const genericFn: (args: { +>genericFn : Symbol(genericFn, Decl(intraExpressionInferences.ts, 201, 13)) +>T : Symbol(T, Decl(intraExpressionInferences.ts, 201, 26)) +>args : Symbol(args, Decl(intraExpressionInferences.ts, 201, 29)) + + parser: (p: unknown, errorFn: ErrorFn) => T; +>parser : Symbol(parser, Decl(intraExpressionInferences.ts, 201, 36)) +>p : Symbol(p, Decl(intraExpressionInferences.ts, 202, 11)) +>errorFn : Symbol(errorFn, Decl(intraExpressionInferences.ts, 202, 22)) +>ErrorFn : Symbol(ErrorFn, Decl(intraExpressionInferences.ts, 197, 2)) +>T : Symbol(T, Decl(intraExpressionInferences.ts, 201, 26)) + + handler: (data: { body: T }) => unknown; +>handler : Symbol(handler, Decl(intraExpressionInferences.ts, 202, 46)) +>data : Symbol(data, Decl(intraExpressionInferences.ts, 203, 12)) +>body : Symbol(body, Decl(intraExpressionInferences.ts, 203, 19)) +>T : Symbol(T, Decl(intraExpressionInferences.ts, 201, 26)) + +}) => T; +>T : Symbol(T, Decl(intraExpressionInferences.ts, 201, 26)) + +declare const createParser: (arg: T) => (p: unknown, errorFn: ErrorFn) => T; +>createParser : Symbol(createParser, Decl(intraExpressionInferences.ts, 206, 13)) +>T : Symbol(T, Decl(intraExpressionInferences.ts, 206, 29)) +>arg : Symbol(arg, Decl(intraExpressionInferences.ts, 206, 32)) +>T : Symbol(T, Decl(intraExpressionInferences.ts, 206, 29)) +>p : Symbol(p, Decl(intraExpressionInferences.ts, 206, 44)) +>errorFn : Symbol(errorFn, Decl(intraExpressionInferences.ts, 206, 55)) +>ErrorFn : Symbol(ErrorFn, Decl(intraExpressionInferences.ts, 197, 2)) +>T : Symbol(T, Decl(intraExpressionInferences.ts, 206, 29)) + +genericFn({ +>genericFn : Symbol(genericFn, Decl(intraExpressionInferences.ts, 201, 13)) + + parser: createParser(1 as const), +>parser : Symbol(parser, Decl(intraExpressionInferences.ts, 208, 11)) +>createParser : Symbol(createParser, Decl(intraExpressionInferences.ts, 206, 13)) +>const : Symbol(const) + + handler: ({ body: _ }) => {}, +>handler : Symbol(handler, Decl(intraExpressionInferences.ts, 209, 35)) +>body : Symbol(body, Decl(intraExpressionInferences.ts, 203, 19)) +>_ : Symbol(_, Decl(intraExpressionInferences.ts, 210, 13)) + +}); + +declare const genericFnTuple: ( +>genericFnTuple : Symbol(genericFnTuple, Decl(intraExpressionInferences.ts, 213, 13)) +>T : Symbol(T, Decl(intraExpressionInferences.ts, 213, 31)) + + args: [ +>args : Symbol(args, Decl(intraExpressionInferences.ts, 213, 34)) + + parser: (p: unknown, errorFn: ErrorFn) => T, +>p : Symbol(p, Decl(intraExpressionInferences.ts, 215, 13)) +>errorFn : Symbol(errorFn, Decl(intraExpressionInferences.ts, 215, 24)) +>ErrorFn : Symbol(ErrorFn, Decl(intraExpressionInferences.ts, 197, 2)) +>T : Symbol(T, Decl(intraExpressionInferences.ts, 213, 31)) + + handler: (data: { body: T }) => unknown +>data : Symbol(data, Decl(intraExpressionInferences.ts, 216, 14)) +>body : Symbol(body, Decl(intraExpressionInferences.ts, 216, 21)) +>T : Symbol(T, Decl(intraExpressionInferences.ts, 213, 31)) + + ] +) => T; +>T : Symbol(T, Decl(intraExpressionInferences.ts, 213, 31)) + +genericFnTuple([createParser(1 as const), ({ body: _ }) => {}]); +>genericFnTuple : Symbol(genericFnTuple, Decl(intraExpressionInferences.ts, 213, 13)) +>createParser : Symbol(createParser, Decl(intraExpressionInferences.ts, 206, 13)) +>const : Symbol(const) +>body : Symbol(body, Decl(intraExpressionInferences.ts, 216, 21)) +>_ : Symbol(_, Decl(intraExpressionInferences.ts, 220, 44)) + diff --git a/tests/baselines/reference/intraExpressionInferences.types b/tests/baselines/reference/intraExpressionInferences.types index 87e12e55daef4..cbf5ae0e93362 100644 --- a/tests/baselines/reference/intraExpressionInferences.types +++ b/tests/baselines/reference/intraExpressionInferences.types @@ -659,3 +659,78 @@ branch({ } }) +type ErrorFn = (error: unknown) => void; +>ErrorFn : (error: unknown) => void +>error : unknown + +declare const genericFn: (args: { +>genericFn : (args: { parser: (p: unknown, errorFn: ErrorFn) => T; handler: (data: { body: T; }) => unknown; }) => T +>args : { parser: (p: unknown, errorFn: ErrorFn) => T; handler: (data: { body: T;}) => unknown; } + + parser: (p: unknown, errorFn: ErrorFn) => T; +>parser : (p: unknown, errorFn: ErrorFn) => T +>p : unknown +>errorFn : ErrorFn + + handler: (data: { body: T }) => unknown; +>handler : (data: { body: T;}) => unknown +>data : { body: T; } +>body : T + +}) => T; + +declare const createParser: (arg: T) => (p: unknown, errorFn: ErrorFn) => T; +>createParser : (arg: T) => (p: unknown, errorFn: ErrorFn) => T +>arg : T +>p : unknown +>errorFn : ErrorFn + +genericFn({ +>genericFn({ parser: createParser(1 as const), handler: ({ body: _ }) => {},}) : 1 +>genericFn : (args: { parser: (p: unknown, errorFn: ErrorFn) => T; handler: (data: { body: T; }) => unknown; }) => T +>{ parser: createParser(1 as const), handler: ({ body: _ }) => {},} : { parser: (p: unknown, errorFn: ErrorFn) => 1; handler: ({ body: _ }: { body: 1; }) => void; } + + parser: createParser(1 as const), +>parser : (p: unknown, errorFn: ErrorFn) => 1 +>createParser(1 as const) : (p: unknown, errorFn: ErrorFn) => 1 +>createParser : (arg: T) => (p: unknown, errorFn: ErrorFn) => T +>1 as const : 1 +>1 : 1 + + handler: ({ body: _ }) => {}, +>handler : ({ body: _ }: { body: 1; }) => void +>({ body: _ }) => {} : ({ body: _ }: { body: 1; }) => void +>body : any +>_ : 1 + +}); + +declare const genericFnTuple: ( +>genericFnTuple : (args: [parser: (p: unknown, errorFn: ErrorFn) => T, handler: (data: { body: T; }) => unknown]) => T + + args: [ +>args : [parser: (p: unknown, errorFn: ErrorFn) => T, handler: (data: { body: T;}) => unknown] + + parser: (p: unknown, errorFn: ErrorFn) => T, +>p : unknown +>errorFn : ErrorFn + + handler: (data: { body: T }) => unknown +>data : { body: T; } +>body : T + + ] +) => T; + +genericFnTuple([createParser(1 as const), ({ body: _ }) => {}]); +>genericFnTuple([createParser(1 as const), ({ body: _ }) => {}]) : 1 +>genericFnTuple : (args: [parser: (p: unknown, errorFn: ErrorFn) => T, handler: (data: { body: T; }) => unknown]) => T +>[createParser(1 as const), ({ body: _ }) => {}] : [(p: unknown, errorFn: ErrorFn) => 1, ({ body: _ }: { body: 1; }) => void] +>createParser(1 as const) : (p: unknown, errorFn: ErrorFn) => 1 +>createParser : (arg: T) => (p: unknown, errorFn: ErrorFn) => T +>1 as const : 1 +>1 : 1 +>({ body: _ }) => {} : ({ body: _ }: { body: 1; }) => void +>body : any +>_ : 1 + diff --git a/tests/baselines/reference/intraExpressionInferencesJsx.symbols b/tests/baselines/reference/intraExpressionInferencesJsx.symbols index 798c76fbcefb5..453fb9e13c2b5 100644 --- a/tests/baselines/reference/intraExpressionInferencesJsx.symbols +++ b/tests/baselines/reference/intraExpressionInferencesJsx.symbols @@ -272,3 +272,48 @@ function Foo(props: Props) { }} />; +type ErrorFn = (error: unknown) => void; +>ErrorFn : Symbol(ErrorFn, Decl(intraExpressionInferencesJsx.tsx, 107, 6)) +>error : Symbol(error, Decl(intraExpressionInferencesJsx.tsx, 109, 16)) + +function GenericComp(props: { +>GenericComp : Symbol(GenericComp, Decl(intraExpressionInferencesJsx.tsx, 109, 40)) +>T : Symbol(T, Decl(intraExpressionInferencesJsx.tsx, 111, 21)) +>props : Symbol(props, Decl(intraExpressionInferencesJsx.tsx, 111, 24)) + + parser: (p: unknown, errorFn: ErrorFn) => T; +>parser : Symbol(parser, Decl(intraExpressionInferencesJsx.tsx, 111, 32)) +>p : Symbol(p, Decl(intraExpressionInferencesJsx.tsx, 112, 11)) +>errorFn : Symbol(errorFn, Decl(intraExpressionInferencesJsx.tsx, 112, 22)) +>ErrorFn : Symbol(ErrorFn, Decl(intraExpressionInferencesJsx.tsx, 107, 6)) +>T : Symbol(T, Decl(intraExpressionInferencesJsx.tsx, 111, 21)) + + handler: (data: { body: T }) => unknown; +>handler : Symbol(handler, Decl(intraExpressionInferencesJsx.tsx, 112, 46)) +>data : Symbol(data, Decl(intraExpressionInferencesJsx.tsx, 113, 12)) +>body : Symbol(body, Decl(intraExpressionInferencesJsx.tsx, 113, 19)) +>T : Symbol(T, Decl(intraExpressionInferencesJsx.tsx, 111, 21)) + +}) { + return null; +} + +declare const createParser: (arg: T) => (p: unknown, errorFn: ErrorFn) => T; +>createParser : Symbol(createParser, Decl(intraExpressionInferencesJsx.tsx, 118, 13)) +>T : Symbol(T, Decl(intraExpressionInferencesJsx.tsx, 118, 29)) +>arg : Symbol(arg, Decl(intraExpressionInferencesJsx.tsx, 118, 32)) +>T : Symbol(T, Decl(intraExpressionInferencesJsx.tsx, 118, 29)) +>p : Symbol(p, Decl(intraExpressionInferencesJsx.tsx, 118, 44)) +>errorFn : Symbol(errorFn, Decl(intraExpressionInferencesJsx.tsx, 118, 55)) +>ErrorFn : Symbol(ErrorFn, Decl(intraExpressionInferencesJsx.tsx, 107, 6)) +>T : Symbol(T, Decl(intraExpressionInferencesJsx.tsx, 118, 29)) + + {}} />; +>GenericComp : Symbol(GenericComp, Decl(intraExpressionInferencesJsx.tsx, 109, 40)) +>parser : Symbol(parser, Decl(intraExpressionInferencesJsx.tsx, 120, 12)) +>createParser : Symbol(createParser, Decl(intraExpressionInferencesJsx.tsx, 118, 13)) +>const : Symbol(const) +>handler : Symbol(handler, Decl(intraExpressionInferencesJsx.tsx, 120, 46)) +>body : Symbol(body, Decl(intraExpressionInferencesJsx.tsx, 113, 19)) +>_ : Symbol(_, Decl(intraExpressionInferencesJsx.tsx, 120, 58)) + diff --git a/tests/baselines/reference/intraExpressionInferencesJsx.types b/tests/baselines/reference/intraExpressionInferencesJsx.types index 642809682ecf5..ce35d324ee894 100644 --- a/tests/baselines/reference/intraExpressionInferencesJsx.types +++ b/tests/baselines/reference/intraExpressionInferencesJsx.types @@ -295,3 +295,44 @@ function Foo(props: Props) { }} />; +type ErrorFn = (error: unknown) => void; +>ErrorFn : (error: unknown) => void +>error : unknown + +function GenericComp(props: { +>GenericComp : (props: { parser: (p: unknown, errorFn: ErrorFn) => T; handler: (data: { body: T;}) => unknown; }) => null +>props : { parser: (p: unknown, errorFn: ErrorFn) => T; handler: (data: { body: T;}) => unknown; } + + parser: (p: unknown, errorFn: ErrorFn) => T; +>parser : (p: unknown, errorFn: ErrorFn) => T +>p : unknown +>errorFn : ErrorFn + + handler: (data: { body: T }) => unknown; +>handler : (data: { body: T;}) => unknown +>data : { body: T; } +>body : T + +}) { + return null; +} + +declare const createParser: (arg: T) => (p: unknown, errorFn: ErrorFn) => T; +>createParser : (arg: T) => (p: unknown, errorFn: ErrorFn) => T +>arg : T +>p : unknown +>errorFn : ErrorFn + + {}} />; +> {}} /> : JSX.Element +>GenericComp : (props: { parser: (p: unknown, errorFn: ErrorFn) => T; handler: (data: { body: T; }) => unknown; }) => null +>parser : (p: unknown, errorFn: ErrorFn) => 1 +>createParser(1 as const) : (p: unknown, errorFn: ErrorFn) => 1 +>createParser : (arg: T) => (p: unknown, errorFn: ErrorFn) => T +>1 as const : 1 +>1 : 1 +>handler : ({ body: _ }: { body: 1; }) => void +>({ body: _ }) => {} : ({ body: _ }: { body: 1; }) => void +>body : any +>_ : 1 + diff --git a/tests/cases/conformance/types/typeRelationships/typeInference/intraExpressionInferences.ts b/tests/cases/conformance/types/typeRelationships/typeInference/intraExpressionInferences.ts index f79902d6ae79d..cb194e67b4a5c 100644 --- a/tests/cases/conformance/types/typeRelationships/typeInference/intraExpressionInferences.ts +++ b/tests/cases/conformance/types/typeRelationships/typeInference/intraExpressionInferences.ts @@ -199,3 +199,26 @@ branch({ let test1: "a" = u } }) + +type ErrorFn = (error: unknown) => void; + +declare const genericFn: (args: { + parser: (p: unknown, errorFn: ErrorFn) => T; + handler: (data: { body: T }) => unknown; +}) => T; + +declare const createParser: (arg: T) => (p: unknown, errorFn: ErrorFn) => T; + +genericFn({ + parser: createParser(1 as const), + handler: ({ body: _ }) => {}, +}); + +declare const genericFnTuple: ( + args: [ + parser: (p: unknown, errorFn: ErrorFn) => T, + handler: (data: { body: T }) => unknown + ] +) => T; + +genericFnTuple([createParser(1 as const), ({ body: _ }) => {}]); \ No newline at end of file diff --git a/tests/cases/conformance/types/typeRelationships/typeInference/intraExpressionInferencesJsx.tsx b/tests/cases/conformance/types/typeRelationships/typeInference/intraExpressionInferencesJsx.tsx index 4ecd4f9e4b62f..63886451a8112 100644 --- a/tests/cases/conformance/types/typeRelationships/typeInference/intraExpressionInferencesJsx.tsx +++ b/tests/cases/conformance/types/typeRelationships/typeInference/intraExpressionInferencesJsx.tsx @@ -110,3 +110,16 @@ function Foo(props: Props) { a: (x) => 10, b: (arg) => { arg.toString(); }, }} />; + +type ErrorFn = (error: unknown) => void; + +function GenericComp(props: { + parser: (p: unknown, errorFn: ErrorFn) => T; + handler: (data: { body: T }) => unknown; +}) { + return null; +} + +declare const createParser: (arg: T) => (p: unknown, errorFn: ErrorFn) => T; + + {}} />; From 299f2645c178318f02fdef369e977f482540be50 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mateusz=20Burzy=C5=84ski?= Date: Thu, 21 Mar 2024 23:11:07 +0100 Subject: [PATCH 2/3] update baselines --- tests/baselines/reference/intraExpressionInferences.types | 4 ++-- tests/baselines/reference/intraExpressionInferencesJsx.types | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/tests/baselines/reference/intraExpressionInferences.types b/tests/baselines/reference/intraExpressionInferences.types index 622032ce821f1..761f184056a7e 100644 --- a/tests/baselines/reference/intraExpressionInferences.types +++ b/tests/baselines/reference/intraExpressionInferences.types @@ -1122,7 +1122,7 @@ type ErrorFn = (error: unknown) => void; >error : unknown declare const genericFn: (args: { ->genericFn : (args: { parser: (p: unknown, errorFn: ErrorFn) => T; handler: (data: { body: T;}) => unknown; }) => T +>genericFn : (args: { parser: (p: unknown, errorFn: ErrorFn) => T; handler: (data: { body: T; }) => unknown;}) => T >args : { parser: (p: unknown, errorFn: ErrorFn) => T; handler: (data: { body: T;}) => unknown; } parser: (p: unknown, errorFn: ErrorFn) => T; @@ -1164,7 +1164,7 @@ genericFn({ }); declare const genericFnTuple: ( ->genericFnTuple : (args: [parser: (p: unknown, errorFn: ErrorFn) => T, handler: (data: { body: T;}) => unknown]) => T +>genericFnTuple : (args: [ parser: (p: unknown, errorFn: ErrorFn) => T, handler: (data: { body: T; }) => unknown]) => T args: [ >args : [parser: (p: unknown, errorFn: ErrorFn) => T, handler: (data: { body: T;}) => unknown] diff --git a/tests/baselines/reference/intraExpressionInferencesJsx.types b/tests/baselines/reference/intraExpressionInferencesJsx.types index 3931b0a9fcc93..c95012a56da6a 100644 --- a/tests/baselines/reference/intraExpressionInferencesJsx.types +++ b/tests/baselines/reference/intraExpressionInferencesJsx.types @@ -308,7 +308,7 @@ type ErrorFn = (error: unknown) => void; >error : unknown function GenericComp(props: { ->GenericComp : (props: { parser: (p: unknown, errorFn: ErrorFn) => T; handler: (data: { body: T;}) => unknown; }) => null +>GenericComp : (props: { parser: (p: unknown, errorFn: ErrorFn) => T; handler: (data: { body: T; }) => unknown;}) => null >props : { parser: (p: unknown, errorFn: ErrorFn) => T; handler: (data: { body: T;}) => unknown; } parser: (p: unknown, errorFn: ErrorFn) => T; From f92136fd1860b46dedfefd359679f72c37f92600 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mateusz=20Burzy=C5=84ski?= Date: Tue, 18 Jun 2024 08:34:33 +0200 Subject: [PATCH 3/3] add an extra test case --- ...essionInferencesNestedGenericCall1.symbols | 294 ++++++++++++++++++ ...pressionInferencesNestedGenericCall1.types | 248 +++++++++++++++ ...aExpressionInferencesNestedGenericCall1.ts | 111 +++++++ 3 files changed, 653 insertions(+) create mode 100644 tests/baselines/reference/intraExpressionInferencesNestedGenericCall1.symbols create mode 100644 tests/baselines/reference/intraExpressionInferencesNestedGenericCall1.types create mode 100644 tests/cases/conformance/types/typeRelationships/typeInference/intraExpressionInferencesNestedGenericCall1.ts diff --git a/tests/baselines/reference/intraExpressionInferencesNestedGenericCall1.symbols b/tests/baselines/reference/intraExpressionInferencesNestedGenericCall1.symbols new file mode 100644 index 0000000000000..1e26325176225 --- /dev/null +++ b/tests/baselines/reference/intraExpressionInferencesNestedGenericCall1.symbols @@ -0,0 +1,294 @@ +//// [tests/cases/conformance/types/typeRelationships/typeInference/intraExpressionInferencesNestedGenericCall1.ts] //// + +=== intraExpressionInferencesNestedGenericCall1.ts === +interface FastifyTypeProvider { +>FastifyTypeProvider : Symbol(FastifyTypeProvider, Decl(intraExpressionInferencesNestedGenericCall1.ts, 0, 0)) + + readonly input: unknown; +>input : Symbol(FastifyTypeProvider.input, Decl(intraExpressionInferencesNestedGenericCall1.ts, 0, 31)) + + readonly output: unknown; +>output : Symbol(FastifyTypeProvider.output, Decl(intraExpressionInferencesNestedGenericCall1.ts, 1, 26)) +} + +export interface FastifyTypeProviderDefault extends FastifyTypeProvider {} +>FastifyTypeProviderDefault : Symbol(FastifyTypeProviderDefault, Decl(intraExpressionInferencesNestedGenericCall1.ts, 3, 1)) +>FastifyTypeProvider : Symbol(FastifyTypeProvider, Decl(intraExpressionInferencesNestedGenericCall1.ts, 0, 0)) + +type CallTypeProvider = (F & { +>CallTypeProvider : Symbol(CallTypeProvider, Decl(intraExpressionInferencesNestedGenericCall1.ts, 5, 74)) +>F : Symbol(F, Decl(intraExpressionInferencesNestedGenericCall1.ts, 7, 22)) +>FastifyTypeProvider : Symbol(FastifyTypeProvider, Decl(intraExpressionInferencesNestedGenericCall1.ts, 0, 0)) +>I : Symbol(I, Decl(intraExpressionInferencesNestedGenericCall1.ts, 7, 52)) +>F : Symbol(F, Decl(intraExpressionInferencesNestedGenericCall1.ts, 7, 22)) + + input: I; +>input : Symbol(input, Decl(intraExpressionInferencesNestedGenericCall1.ts, 7, 64)) +>I : Symbol(I, Decl(intraExpressionInferencesNestedGenericCall1.ts, 7, 52)) + +})["output"]; +type UndefinedToUnknown = [T] extends [undefined] ? unknown : T; +>UndefinedToUnknown : Symbol(UndefinedToUnknown, Decl(intraExpressionInferencesNestedGenericCall1.ts, 9, 13)) +>T : Symbol(T, Decl(intraExpressionInferencesNestedGenericCall1.ts, 10, 24)) +>T : Symbol(T, Decl(intraExpressionInferencesNestedGenericCall1.ts, 10, 24)) +>T : Symbol(T, Decl(intraExpressionInferencesNestedGenericCall1.ts, 10, 24)) + +interface RouteGenericInterface { +>RouteGenericInterface : Symbol(RouteGenericInterface, Decl(intraExpressionInferencesNestedGenericCall1.ts, 10, 67)) + + Querystring?: unknown; +>Querystring : Symbol(RouteGenericInterface.Querystring, Decl(intraExpressionInferencesNestedGenericCall1.ts, 12, 33)) +} + +interface FastifySchema { +>FastifySchema : Symbol(FastifySchema, Decl(intraExpressionInferencesNestedGenericCall1.ts, 14, 1)) + + querystring?: unknown; +>querystring : Symbol(FastifySchema.querystring, Decl(intraExpressionInferencesNestedGenericCall1.ts, 16, 25)) + + headers?: unknown; +>headers : Symbol(FastifySchema.headers, Decl(intraExpressionInferencesNestedGenericCall1.ts, 17, 24)) +} + +interface FastifyRequestType { +>FastifyRequestType : Symbol(FastifyRequestType, Decl(intraExpressionInferencesNestedGenericCall1.ts, 19, 1)) +>Querystring : Symbol(Querystring, Decl(intraExpressionInferencesNestedGenericCall1.ts, 21, 29)) + + query: Querystring; +>query : Symbol(FastifyRequestType.query, Decl(intraExpressionInferencesNestedGenericCall1.ts, 21, 53)) +>Querystring : Symbol(Querystring, Decl(intraExpressionInferencesNestedGenericCall1.ts, 21, 29)) +} + +type ResolveRequestQuerystring< +>ResolveRequestQuerystring : Symbol(ResolveRequestQuerystring, Decl(intraExpressionInferencesNestedGenericCall1.ts, 23, 1)) + + TypeProvider extends FastifyTypeProvider, +>TypeProvider : Symbol(TypeProvider, Decl(intraExpressionInferencesNestedGenericCall1.ts, 25, 31)) +>FastifyTypeProvider : Symbol(FastifyTypeProvider, Decl(intraExpressionInferencesNestedGenericCall1.ts, 0, 0)) + + SchemaCompiler extends FastifySchema, +>SchemaCompiler : Symbol(SchemaCompiler, Decl(intraExpressionInferencesNestedGenericCall1.ts, 26, 43)) +>FastifySchema : Symbol(FastifySchema, Decl(intraExpressionInferencesNestedGenericCall1.ts, 14, 1)) + +> = UndefinedToUnknown< +>UndefinedToUnknown : Symbol(UndefinedToUnknown, Decl(intraExpressionInferencesNestedGenericCall1.ts, 9, 13)) + + CallTypeProvider +>CallTypeProvider : Symbol(CallTypeProvider, Decl(intraExpressionInferencesNestedGenericCall1.ts, 5, 74)) +>TypeProvider : Symbol(TypeProvider, Decl(intraExpressionInferencesNestedGenericCall1.ts, 25, 31)) +>SchemaCompiler : Symbol(SchemaCompiler, Decl(intraExpressionInferencesNestedGenericCall1.ts, 26, 43)) + +>; + +interface ResolveFastifyRequestType< +>ResolveFastifyRequestType : Symbol(ResolveFastifyRequestType, Decl(intraExpressionInferencesNestedGenericCall1.ts, 30, 2)) + + TypeProvider extends FastifyTypeProvider, +>TypeProvider : Symbol(TypeProvider, Decl(intraExpressionInferencesNestedGenericCall1.ts, 32, 36)) +>FastifyTypeProvider : Symbol(FastifyTypeProvider, Decl(intraExpressionInferencesNestedGenericCall1.ts, 0, 0)) + + SchemaCompiler extends FastifySchema, +>SchemaCompiler : Symbol(SchemaCompiler, Decl(intraExpressionInferencesNestedGenericCall1.ts, 33, 43)) +>FastifySchema : Symbol(FastifySchema, Decl(intraExpressionInferencesNestedGenericCall1.ts, 14, 1)) + +> { + query: ResolveRequestQuerystring; +>query : Symbol(ResolveFastifyRequestType.query, Decl(intraExpressionInferencesNestedGenericCall1.ts, 35, 3)) +>ResolveRequestQuerystring : Symbol(ResolveRequestQuerystring, Decl(intraExpressionInferencesNestedGenericCall1.ts, 23, 1)) +>TypeProvider : Symbol(TypeProvider, Decl(intraExpressionInferencesNestedGenericCall1.ts, 32, 36)) +>SchemaCompiler : Symbol(SchemaCompiler, Decl(intraExpressionInferencesNestedGenericCall1.ts, 33, 43)) +} + +interface FastifyRequest< +>FastifyRequest : Symbol(FastifyRequest, Decl(intraExpressionInferencesNestedGenericCall1.ts, 37, 1)) + + RouteGeneric extends RouteGenericInterface = RouteGenericInterface, +>RouteGeneric : Symbol(RouteGeneric, Decl(intraExpressionInferencesNestedGenericCall1.ts, 39, 25)) +>RouteGenericInterface : Symbol(RouteGenericInterface, Decl(intraExpressionInferencesNestedGenericCall1.ts, 10, 67)) +>RouteGenericInterface : Symbol(RouteGenericInterface, Decl(intraExpressionInferencesNestedGenericCall1.ts, 10, 67)) + + SchemaCompiler extends FastifySchema = FastifySchema, +>SchemaCompiler : Symbol(SchemaCompiler, Decl(intraExpressionInferencesNestedGenericCall1.ts, 40, 69)) +>FastifySchema : Symbol(FastifySchema, Decl(intraExpressionInferencesNestedGenericCall1.ts, 14, 1)) +>FastifySchema : Symbol(FastifySchema, Decl(intraExpressionInferencesNestedGenericCall1.ts, 14, 1)) + + TypeProvider extends FastifyTypeProvider = FastifyTypeProviderDefault, +>TypeProvider : Symbol(TypeProvider, Decl(intraExpressionInferencesNestedGenericCall1.ts, 41, 55)) +>FastifyTypeProvider : Symbol(FastifyTypeProvider, Decl(intraExpressionInferencesNestedGenericCall1.ts, 0, 0)) +>FastifyTypeProviderDefault : Symbol(FastifyTypeProviderDefault, Decl(intraExpressionInferencesNestedGenericCall1.ts, 3, 1)) + + RequestType extends FastifyRequestType = ResolveFastifyRequestType< +>RequestType : Symbol(RequestType, Decl(intraExpressionInferencesNestedGenericCall1.ts, 42, 72)) +>FastifyRequestType : Symbol(FastifyRequestType, Decl(intraExpressionInferencesNestedGenericCall1.ts, 19, 1)) +>ResolveFastifyRequestType : Symbol(ResolveFastifyRequestType, Decl(intraExpressionInferencesNestedGenericCall1.ts, 30, 2)) + + TypeProvider, +>TypeProvider : Symbol(TypeProvider, Decl(intraExpressionInferencesNestedGenericCall1.ts, 41, 55)) + + SchemaCompiler +>SchemaCompiler : Symbol(SchemaCompiler, Decl(intraExpressionInferencesNestedGenericCall1.ts, 40, 69)) + + >, +> { + query: RequestType["query"]; +>query : Symbol(FastifyRequest.query, Decl(intraExpressionInferencesNestedGenericCall1.ts, 47, 3)) +>RequestType : Symbol(RequestType, Decl(intraExpressionInferencesNestedGenericCall1.ts, 42, 72)) +} + +interface RouteOptions< +>RouteOptions : Symbol(RouteOptions, Decl(intraExpressionInferencesNestedGenericCall1.ts, 49, 1)) + + RouteGeneric extends RouteGenericInterface, +>RouteGeneric : Symbol(RouteGeneric, Decl(intraExpressionInferencesNestedGenericCall1.ts, 51, 23)) +>RouteGenericInterface : Symbol(RouteGenericInterface, Decl(intraExpressionInferencesNestedGenericCall1.ts, 10, 67)) + + SchemaCompiler extends FastifySchema, +>SchemaCompiler : Symbol(SchemaCompiler, Decl(intraExpressionInferencesNestedGenericCall1.ts, 52, 45)) +>FastifySchema : Symbol(FastifySchema, Decl(intraExpressionInferencesNestedGenericCall1.ts, 14, 1)) + + TypeProvider extends FastifyTypeProvider, +>TypeProvider : Symbol(TypeProvider, Decl(intraExpressionInferencesNestedGenericCall1.ts, 53, 39)) +>FastifyTypeProvider : Symbol(FastifyTypeProvider, Decl(intraExpressionInferencesNestedGenericCall1.ts, 0, 0)) + +> { + schema?: SchemaCompiler; +>schema : Symbol(RouteOptions.schema, Decl(intraExpressionInferencesNestedGenericCall1.ts, 55, 3)) +>SchemaCompiler : Symbol(SchemaCompiler, Decl(intraExpressionInferencesNestedGenericCall1.ts, 52, 45)) + + onRequest?: ( +>onRequest : Symbol(RouteOptions.onRequest, Decl(intraExpressionInferencesNestedGenericCall1.ts, 56, 26)) + + request: FastifyRequest, +>request : Symbol(request, Decl(intraExpressionInferencesNestedGenericCall1.ts, 57, 15)) +>FastifyRequest : Symbol(FastifyRequest, Decl(intraExpressionInferencesNestedGenericCall1.ts, 37, 1)) +>RouteGeneric : Symbol(RouteGeneric, Decl(intraExpressionInferencesNestedGenericCall1.ts, 51, 23)) +>SchemaCompiler : Symbol(SchemaCompiler, Decl(intraExpressionInferencesNestedGenericCall1.ts, 52, 45)) +>TypeProvider : Symbol(TypeProvider, Decl(intraExpressionInferencesNestedGenericCall1.ts, 53, 39)) + + ) => void; + method: "GET" | "POST"; +>method : Symbol(RouteOptions.method, Decl(intraExpressionInferencesNestedGenericCall1.ts, 59, 12)) + + url: string; +>url : Symbol(RouteOptions.url, Decl(intraExpressionInferencesNestedGenericCall1.ts, 60, 25)) + + handler: ( +>handler : Symbol(RouteOptions.handler, Decl(intraExpressionInferencesNestedGenericCall1.ts, 61, 14)) + + request: FastifyRequest, +>request : Symbol(request, Decl(intraExpressionInferencesNestedGenericCall1.ts, 62, 12)) +>FastifyRequest : Symbol(FastifyRequest, Decl(intraExpressionInferencesNestedGenericCall1.ts, 37, 1)) +>RouteGeneric : Symbol(RouteGeneric, Decl(intraExpressionInferencesNestedGenericCall1.ts, 51, 23)) +>SchemaCompiler : Symbol(SchemaCompiler, Decl(intraExpressionInferencesNestedGenericCall1.ts, 52, 45)) +>TypeProvider : Symbol(TypeProvider, Decl(intraExpressionInferencesNestedGenericCall1.ts, 53, 39)) + + ) => void; +} + +interface FastifyInstance { +>FastifyInstance : Symbol(FastifyInstance, Decl(intraExpressionInferencesNestedGenericCall1.ts, 65, 1)) +>TypeProvider : Symbol(TypeProvider, Decl(intraExpressionInferencesNestedGenericCall1.ts, 67, 26)) +>FastifyTypeProvider : Symbol(FastifyTypeProvider, Decl(intraExpressionInferencesNestedGenericCall1.ts, 0, 0)) + + route< +>route : Symbol(FastifyInstance.route, Decl(intraExpressionInferencesNestedGenericCall1.ts, 67, 69)) + + RouteGeneric extends RouteGenericInterface, +>RouteGeneric : Symbol(RouteGeneric, Decl(intraExpressionInferencesNestedGenericCall1.ts, 68, 8)) +>RouteGenericInterface : Symbol(RouteGenericInterface, Decl(intraExpressionInferencesNestedGenericCall1.ts, 10, 67)) + + SchemaCompiler extends FastifySchema, +>SchemaCompiler : Symbol(SchemaCompiler, Decl(intraExpressionInferencesNestedGenericCall1.ts, 69, 47)) +>FastifySchema : Symbol(FastifySchema, Decl(intraExpressionInferencesNestedGenericCall1.ts, 14, 1)) + + >( + opts: RouteOptions, +>opts : Symbol(opts, Decl(intraExpressionInferencesNestedGenericCall1.ts, 71, 4)) +>RouteOptions : Symbol(RouteOptions, Decl(intraExpressionInferencesNestedGenericCall1.ts, 49, 1)) +>RouteGeneric : Symbol(RouteGeneric, Decl(intraExpressionInferencesNestedGenericCall1.ts, 68, 8)) +>SchemaCompiler : Symbol(SchemaCompiler, Decl(intraExpressionInferencesNestedGenericCall1.ts, 69, 47)) +>TypeProvider : Symbol(TypeProvider, Decl(intraExpressionInferencesNestedGenericCall1.ts, 67, 26)) + + ): void; +} + +type Type = { +>Type : Symbol(Type, Decl(intraExpressionInferencesNestedGenericCall1.ts, 74, 1)) +>Output : Symbol(Output, Decl(intraExpressionInferencesNestedGenericCall1.ts, 76, 10)) + + _output: Output; +>_output : Symbol(_output, Decl(intraExpressionInferencesNestedGenericCall1.ts, 76, 21)) +>Output : Symbol(Output, Decl(intraExpressionInferencesNestedGenericCall1.ts, 76, 10)) + +}; + +declare function string(): Type; +>string : Symbol(string, Decl(intraExpressionInferencesNestedGenericCall1.ts, 78, 2)) +>Type : Symbol(Type, Decl(intraExpressionInferencesNestedGenericCall1.ts, 74, 1)) + +interface ZodTypeProvider extends FastifyTypeProvider { +>ZodTypeProvider : Symbol(ZodTypeProvider, Decl(intraExpressionInferencesNestedGenericCall1.ts, 80, 40)) +>FastifyTypeProvider : Symbol(FastifyTypeProvider, Decl(intraExpressionInferencesNestedGenericCall1.ts, 0, 0)) + + output: this["input"] extends { _output: unknown } +>output : Symbol(ZodTypeProvider.output, Decl(intraExpressionInferencesNestedGenericCall1.ts, 82, 55)) +>_output : Symbol(_output, Decl(intraExpressionInferencesNestedGenericCall1.ts, 83, 33)) + + ? this["input"]["_output"] + : never; +} + +const verifyAuth = +>verifyAuth : Symbol(verifyAuth, Decl(intraExpressionInferencesNestedGenericCall1.ts, 88, 5)) + + () => +>T : Symbol(T, Decl(intraExpressionInferencesNestedGenericCall1.ts, 89, 3)) +>FastifyRequest : Symbol(FastifyRequest, Decl(intraExpressionInferencesNestedGenericCall1.ts, 37, 1)) + + (req: T) => {}; +>req : Symbol(req, Decl(intraExpressionInferencesNestedGenericCall1.ts, 90, 3)) +>T : Symbol(T, Decl(intraExpressionInferencesNestedGenericCall1.ts, 89, 3)) + +declare const server: FastifyInstance; +>server : Symbol(server, Decl(intraExpressionInferencesNestedGenericCall1.ts, 92, 13)) +>FastifyInstance : Symbol(FastifyInstance, Decl(intraExpressionInferencesNestedGenericCall1.ts, 65, 1)) +>ZodTypeProvider : Symbol(ZodTypeProvider, Decl(intraExpressionInferencesNestedGenericCall1.ts, 80, 40)) + +server.route({ +>server.route : Symbol(FastifyInstance.route, Decl(intraExpressionInferencesNestedGenericCall1.ts, 67, 69)) +>server : Symbol(server, Decl(intraExpressionInferencesNestedGenericCall1.ts, 92, 13)) +>route : Symbol(FastifyInstance.route, Decl(intraExpressionInferencesNestedGenericCall1.ts, 67, 69)) + + url: "/config", +>url : Symbol(url, Decl(intraExpressionInferencesNestedGenericCall1.ts, 94, 14)) + + method: "GET", +>method : Symbol(method, Decl(intraExpressionInferencesNestedGenericCall1.ts, 95, 17)) + + schema: { +>schema : Symbol(schema, Decl(intraExpressionInferencesNestedGenericCall1.ts, 96, 16)) + + querystring: string(), +>querystring : Symbol(querystring, Decl(intraExpressionInferencesNestedGenericCall1.ts, 97, 11)) +>string : Symbol(string, Decl(intraExpressionInferencesNestedGenericCall1.ts, 78, 2)) + + }, + onRequest: verifyAuth(), +>onRequest : Symbol(onRequest, Decl(intraExpressionInferencesNestedGenericCall1.ts, 99, 4)) +>verifyAuth : Symbol(verifyAuth, Decl(intraExpressionInferencesNestedGenericCall1.ts, 88, 5)) + + handler: async (req) => { +>handler : Symbol(handler, Decl(intraExpressionInferencesNestedGenericCall1.ts, 100, 26)) +>req : Symbol(req, Decl(intraExpressionInferencesNestedGenericCall1.ts, 101, 18)) + + const query: string = req.query; +>query : Symbol(query, Decl(intraExpressionInferencesNestedGenericCall1.ts, 102, 9)) +>req.query : Symbol(FastifyRequest.query, Decl(intraExpressionInferencesNestedGenericCall1.ts, 47, 3)) +>req : Symbol(req, Decl(intraExpressionInferencesNestedGenericCall1.ts, 101, 18)) +>query : Symbol(FastifyRequest.query, Decl(intraExpressionInferencesNestedGenericCall1.ts, 47, 3)) + + }, +}); + +export {}; + diff --git a/tests/baselines/reference/intraExpressionInferencesNestedGenericCall1.types b/tests/baselines/reference/intraExpressionInferencesNestedGenericCall1.types new file mode 100644 index 0000000000000..373f303dfb9d9 --- /dev/null +++ b/tests/baselines/reference/intraExpressionInferencesNestedGenericCall1.types @@ -0,0 +1,248 @@ +//// [tests/cases/conformance/types/typeRelationships/typeInference/intraExpressionInferencesNestedGenericCall1.ts] //// + +=== intraExpressionInferencesNestedGenericCall1.ts === +interface FastifyTypeProvider { + readonly input: unknown; +>input : unknown +> : ^^^^^^^ + + readonly output: unknown; +>output : unknown +> : ^^^^^^^ +} + +export interface FastifyTypeProviderDefault extends FastifyTypeProvider {} + +type CallTypeProvider = (F & { +>CallTypeProvider : CallTypeProvider +> : ^^^^^^^^^^^^^^^^^^^^^^ + + input: I; +>input : I +> : ^ + +})["output"]; +type UndefinedToUnknown = [T] extends [undefined] ? unknown : T; +>UndefinedToUnknown : UndefinedToUnknown +> : ^^^^^^^^^^^^^^^^^^^^^ + +interface RouteGenericInterface { + Querystring?: unknown; +>Querystring : unknown +> : ^^^^^^^ +} + +interface FastifySchema { + querystring?: unknown; +>querystring : unknown +> : ^^^^^^^ + + headers?: unknown; +>headers : unknown +> : ^^^^^^^ +} + +interface FastifyRequestType { + query: Querystring; +>query : Querystring +> : ^^^^^^^^^^^ +} + +type ResolveRequestQuerystring< +>ResolveRequestQuerystring : ResolveRequestQuerystring +> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + + TypeProvider extends FastifyTypeProvider, + SchemaCompiler extends FastifySchema, +> = UndefinedToUnknown< + CallTypeProvider +>; + +interface ResolveFastifyRequestType< + TypeProvider extends FastifyTypeProvider, + SchemaCompiler extends FastifySchema, +> { + query: ResolveRequestQuerystring; +>query : UndefinedToUnknown> +> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +} + +interface FastifyRequest< + RouteGeneric extends RouteGenericInterface = RouteGenericInterface, + SchemaCompiler extends FastifySchema = FastifySchema, + TypeProvider extends FastifyTypeProvider = FastifyTypeProviderDefault, + RequestType extends FastifyRequestType = ResolveFastifyRequestType< + TypeProvider, + SchemaCompiler + >, +> { + query: RequestType["query"]; +>query : RequestType["query"] +> : ^^^^^^^^^^^^^^^^^^^^ +} + +interface RouteOptions< + RouteGeneric extends RouteGenericInterface, + SchemaCompiler extends FastifySchema, + TypeProvider extends FastifyTypeProvider, +> { + schema?: SchemaCompiler; +>schema : SchemaCompiler | undefined +> : ^^^^^^^^^^^^^^^^^^^^^^^^^^ + + onRequest?: ( +>onRequest : ((request: FastifyRequest) => void) | undefined +> : ^^ ^^ ^^^^^ ^^^^^^^^^^^^^ + + request: FastifyRequest, +>request : FastifyRequest> +> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + + ) => void; + method: "GET" | "POST"; +>method : "GET" | "POST" +> : ^^^^^^^^^^^^^^ + + url: string; +>url : string +> : ^^^^^^ + + handler: ( +>handler : (request: FastifyRequest) => void +> : ^ ^^ ^^^^^ + + request: FastifyRequest, +>request : FastifyRequest> +> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + + ) => void; +} + +interface FastifyInstance { + route< +>route : (opts: RouteOptions) => void +> : ^ ^^^^^^^^^ ^^ ^^^^^^^^^ ^^ ^^ ^^^^^ + + RouteGeneric extends RouteGenericInterface, + SchemaCompiler extends FastifySchema, + >( + opts: RouteOptions, +>opts : RouteOptions +> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + + ): void; +} + +type Type = { +>Type : Type +> : ^^^^^^^^^^^^ + + _output: Output; +>_output : Output +> : ^^^^^^ + +}; + +declare function string(): Type; +>string : () => Type +> : ^^^^^^ + +interface ZodTypeProvider extends FastifyTypeProvider { + output: this["input"] extends { _output: unknown } +>output : this["input"] extends { _output: unknown; } ? this["input"]["_output"] : never +> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +>_output : unknown +> : ^^^^^^^ + + ? this["input"]["_output"] + : never; +} + +const verifyAuth = +>verifyAuth : () => (req: T) => void +> : ^ ^^^^^^^^^ ^^^^^^^^ ^^ ^^^^^^^^^ + + () => +>() => (req: T) => {} : () => (req: T) => void +> : ^ ^^^^^^^^^ ^^^^^^^^ ^^ ^^^^^^^^^ + + (req: T) => {}; +>(req: T) => {} : (req: T) => void +> : ^ ^^ ^^^^^^^^^ +>req : T +> : ^ + +declare const server: FastifyInstance; +>server : FastifyInstance +> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +server.route({ +>server.route({ url: "/config", method: "GET", schema: { querystring: string(), }, onRequest: verifyAuth(), handler: async (req) => { const query: string = req.query; },}) : void +> : ^^^^ +>server.route : (opts: RouteOptions) => void +> : ^ ^^^^^^^^^ ^^ ^^^^^^^^^ ^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +>server : FastifyInstance +> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +>route : (opts: RouteOptions) => void +> : ^ ^^^^^^^^^ ^^ ^^^^^^^^^ ^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +>{ url: "/config", method: "GET", schema: { querystring: string(), }, onRequest: verifyAuth(), handler: async (req) => { const query: string = req.query; },} : { url: string; method: "GET"; schema: { querystring: Type; }; onRequest: (req: FastifyRequest>) => void; handler: (req: FastifyRequest; }, ZodTypeProvider, ResolveFastifyRequestType; }>>) => Promise; } +> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + + url: "/config", +>url : string +> : ^^^^^^ +>"/config" : "/config" +> : ^^^^^^^^^ + + method: "GET", +>method : "GET" +> : ^^^^^ +>"GET" : "GET" +> : ^^^^^ + + schema: { +>schema : { querystring: Type; } +> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +>{ querystring: string(), } : { querystring: Type; } +> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + + querystring: string(), +>querystring : Type +> : ^^^^^^^^^^^^ +>string() : Type +> : ^^^^^^^^^^^^ +>string : () => Type +> : ^^^^^^ + + }, + onRequest: verifyAuth(), +>onRequest : (req: FastifyRequest>) => void +> : ^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +>verifyAuth() : (req: FastifyRequest>) => void +> : ^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +>verifyAuth : () => (req: T) => void +> : ^ ^^^^^^^^^ ^^^^^^^^ ^^ ^^^^^^^^^ + + handler: async (req) => { +>handler : (req: FastifyRequest; }, ZodTypeProvider, ResolveFastifyRequestType; }>>) => Promise +> : ^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +>async (req) => { const query: string = req.query; } : (req: FastifyRequest; }, ZodTypeProvider, ResolveFastifyRequestType; }>>) => Promise +> : ^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +>req : FastifyRequest; }, ZodTypeProvider, ResolveFastifyRequestType; }>> +> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + + const query: string = req.query; +>query : string +> : ^^^^^^ +>req.query : string +> : ^^^^^^ +>req : FastifyRequest; }, ZodTypeProvider, ResolveFastifyRequestType; }>> +> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +>query : string +> : ^^^^^^ + + }, +}); + +export {}; + diff --git a/tests/cases/conformance/types/typeRelationships/typeInference/intraExpressionInferencesNestedGenericCall1.ts b/tests/cases/conformance/types/typeRelationships/typeInference/intraExpressionInferencesNestedGenericCall1.ts new file mode 100644 index 0000000000000..e3be2a4d0f723 --- /dev/null +++ b/tests/cases/conformance/types/typeRelationships/typeInference/intraExpressionInferencesNestedGenericCall1.ts @@ -0,0 +1,111 @@ +// @strict: true +// @lib: esnext +// @noEmit: true + +interface FastifyTypeProvider { + readonly input: unknown; + readonly output: unknown; +} + +export interface FastifyTypeProviderDefault extends FastifyTypeProvider {} + +type CallTypeProvider = (F & { + input: I; +})["output"]; +type UndefinedToUnknown = [T] extends [undefined] ? unknown : T; + +interface RouteGenericInterface { + Querystring?: unknown; +} + +interface FastifySchema { + querystring?: unknown; + headers?: unknown; +} + +interface FastifyRequestType { + query: Querystring; +} + +type ResolveRequestQuerystring< + TypeProvider extends FastifyTypeProvider, + SchemaCompiler extends FastifySchema, +> = UndefinedToUnknown< + CallTypeProvider +>; + +interface ResolveFastifyRequestType< + TypeProvider extends FastifyTypeProvider, + SchemaCompiler extends FastifySchema, +> { + query: ResolveRequestQuerystring; +} + +interface FastifyRequest< + RouteGeneric extends RouteGenericInterface = RouteGenericInterface, + SchemaCompiler extends FastifySchema = FastifySchema, + TypeProvider extends FastifyTypeProvider = FastifyTypeProviderDefault, + RequestType extends FastifyRequestType = ResolveFastifyRequestType< + TypeProvider, + SchemaCompiler + >, +> { + query: RequestType["query"]; +} + +interface RouteOptions< + RouteGeneric extends RouteGenericInterface, + SchemaCompiler extends FastifySchema, + TypeProvider extends FastifyTypeProvider, +> { + schema?: SchemaCompiler; + onRequest?: ( + request: FastifyRequest, + ) => void; + method: "GET" | "POST"; + url: string; + handler: ( + request: FastifyRequest, + ) => void; +} + +interface FastifyInstance { + route< + RouteGeneric extends RouteGenericInterface, + SchemaCompiler extends FastifySchema, + >( + opts: RouteOptions, + ): void; +} + +type Type = { + _output: Output; +}; + +declare function string(): Type; + +interface ZodTypeProvider extends FastifyTypeProvider { + output: this["input"] extends { _output: unknown } + ? this["input"]["_output"] + : never; +} + +const verifyAuth = + () => + (req: T) => {}; + +declare const server: FastifyInstance; + +server.route({ + url: "/config", + method: "GET", + schema: { + querystring: string(), + }, + onRequest: verifyAuth(), + handler: async (req) => { + const query: string = req.query; + }, +}); + +export {};