diff --git a/src/compiler/expressionToTypeNode.ts b/src/compiler/expressionToTypeNode.ts index 0df3a399b8f14..10cdb4bbc2c3c 100644 --- a/src/compiler/expressionToTypeNode.ts +++ b/src/compiler/expressionToTypeNode.ts @@ -731,6 +731,9 @@ export function createSyntacticTypeNodeBuilder( case SyntaxKind.ConstructorType: case SyntaxKind.FunctionExpression: case SyntaxKind.ArrowFunction: + // Don't report inference fallback for function expressions that are arguments to call expressions + const shouldReportFallback = !(node.kind === SyntaxKind.FunctionExpression || node.kind === SyntaxKind.ArrowFunction) || !isCallExpression(node.parent); + return createReturnFromSignature(node, symbol, context, shouldReportFallback); case SyntaxKind.JSDocFunctionType: case SyntaxKind.JSDocSignature: return createReturnFromSignature(node, symbol, context); @@ -968,7 +971,9 @@ export function createSyntacticTypeNodeBuilder( return failed; } function typeFromFunctionLikeExpression(fnNode: FunctionExpression | ArrowFunction, context: SyntacticTypeNodeBuilderContext) { - const returnType = createReturnFromSignature(fnNode, /*symbol*/ undefined, context); + // Don't report inference fallback for function expressions that are arguments to call expressions + const shouldReportFallback = !isCallExpression(fnNode.parent); + const returnType = createReturnFromSignature(fnNode, /*symbol*/ undefined, context, shouldReportFallback); const typeParameters = reuseTypeParameters(fnNode.typeParameters, context); const parameters = fnNode.parameters.map(p => ensureParameter(p, context)); return syntacticResult( diff --git a/tests/baselines/reference/isolatedDeclarationsFunctionExpressionInCall.errors.txt b/tests/baselines/reference/isolatedDeclarationsFunctionExpressionInCall.errors.txt new file mode 100644 index 0000000000000..fd15b62fdaf83 --- /dev/null +++ b/tests/baselines/reference/isolatedDeclarationsFunctionExpressionInCall.errors.txt @@ -0,0 +1,37 @@ +isolatedDeclarationsFunctionExpressionInCall.ts(4,14): error TS9010: Variable must have an explicit type annotation with --isolatedDeclarations. +isolatedDeclarationsFunctionExpressionInCall.ts(8,14): error TS9010: Variable must have an explicit type annotation with --isolatedDeclarations. +isolatedDeclarationsFunctionExpressionInCall.ts(12,14): error TS9010: Variable must have an explicit type annotation with --isolatedDeclarations. +isolatedDeclarationsFunctionExpressionInCall.ts(16,14): error TS9010: Variable must have an explicit type annotation with --isolatedDeclarations. + + +==== isolatedDeclarationsFunctionExpressionInCall.ts (4 errors) ==== + declare function observer(fn: T): T; + declare function action(fn: T): T; + + export const Component = observer(() => { + ~~~~~~~~~ +!!! error TS9010: Variable must have an explicit type annotation with --isolatedDeclarations. +!!! related TS9027 isolatedDeclarationsFunctionExpressionInCall.ts:4:14: Add a type annotation to the variable Component. + return "hello"; + }); + + export const thing = action(function () { + ~~~~~ +!!! error TS9010: Variable must have an explicit type annotation with --isolatedDeclarations. +!!! related TS9027 isolatedDeclarationsFunctionExpressionInCall.ts:8:14: Add a type annotation to the variable thing. + return Component; + }); + + export const arrowWithType = observer((): string => { + ~~~~~~~~~~~~~ +!!! error TS9010: Variable must have an explicit type annotation with --isolatedDeclarations. +!!! related TS9027 isolatedDeclarationsFunctionExpressionInCall.ts:12:14: Add a type annotation to the variable arrowWithType. + return "typed"; + }); + + export const functionWithType = action(function (): typeof Component { + ~~~~~~~~~~~~~~~~ +!!! error TS9010: Variable must have an explicit type annotation with --isolatedDeclarations. +!!! related TS9027 isolatedDeclarationsFunctionExpressionInCall.ts:16:14: Add a type annotation to the variable functionWithType. + return Component; + }); \ No newline at end of file diff --git a/tests/baselines/reference/isolatedDeclarationsFunctionExpressionInCall.js b/tests/baselines/reference/isolatedDeclarationsFunctionExpressionInCall.js new file mode 100644 index 0000000000000..a564a4355c0b3 --- /dev/null +++ b/tests/baselines/reference/isolatedDeclarationsFunctionExpressionInCall.js @@ -0,0 +1,38 @@ +//// [tests/cases/compiler/isolatedDeclarationsFunctionExpressionInCall.ts] //// + +//// [isolatedDeclarationsFunctionExpressionInCall.ts] +declare function observer(fn: T): T; +declare function action(fn: T): T; + +export const Component = observer(() => { + return "hello"; +}); + +export const thing = action(function () { + return Component; +}); + +export const arrowWithType = observer((): string => { + return "typed"; +}); + +export const functionWithType = action(function (): typeof Component { + return Component; +}); + +//// [isolatedDeclarationsFunctionExpressionInCall.js] +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.functionWithType = exports.arrowWithType = exports.thing = exports.Component = void 0; +exports.Component = observer(function () { + return "hello"; +}); +exports.thing = action(function () { + return exports.Component; +}); +exports.arrowWithType = observer(function () { + return "typed"; +}); +exports.functionWithType = action(function () { + return exports.Component; +}); diff --git a/tests/baselines/reference/isolatedDeclarationsFunctionExpressionInCall.symbols b/tests/baselines/reference/isolatedDeclarationsFunctionExpressionInCall.symbols new file mode 100644 index 0000000000000..f49dd100fd1b0 --- /dev/null +++ b/tests/baselines/reference/isolatedDeclarationsFunctionExpressionInCall.symbols @@ -0,0 +1,49 @@ +//// [tests/cases/compiler/isolatedDeclarationsFunctionExpressionInCall.ts] //// + +=== isolatedDeclarationsFunctionExpressionInCall.ts === +declare function observer(fn: T): T; +>observer : Symbol(observer, Decl(isolatedDeclarationsFunctionExpressionInCall.ts, 0, 0)) +>T : Symbol(T, Decl(isolatedDeclarationsFunctionExpressionInCall.ts, 0, 26)) +>fn : Symbol(fn, Decl(isolatedDeclarationsFunctionExpressionInCall.ts, 0, 29)) +>T : Symbol(T, Decl(isolatedDeclarationsFunctionExpressionInCall.ts, 0, 26)) +>T : Symbol(T, Decl(isolatedDeclarationsFunctionExpressionInCall.ts, 0, 26)) + +declare function action(fn: T): T; +>action : Symbol(action, Decl(isolatedDeclarationsFunctionExpressionInCall.ts, 0, 39)) +>T : Symbol(T, Decl(isolatedDeclarationsFunctionExpressionInCall.ts, 1, 24)) +>fn : Symbol(fn, Decl(isolatedDeclarationsFunctionExpressionInCall.ts, 1, 27)) +>T : Symbol(T, Decl(isolatedDeclarationsFunctionExpressionInCall.ts, 1, 24)) +>T : Symbol(T, Decl(isolatedDeclarationsFunctionExpressionInCall.ts, 1, 24)) + +export const Component = observer(() => { +>Component : Symbol(Component, Decl(isolatedDeclarationsFunctionExpressionInCall.ts, 3, 12)) +>observer : Symbol(observer, Decl(isolatedDeclarationsFunctionExpressionInCall.ts, 0, 0)) + + return "hello"; +}); + +export const thing = action(function () { +>thing : Symbol(thing, Decl(isolatedDeclarationsFunctionExpressionInCall.ts, 7, 12)) +>action : Symbol(action, Decl(isolatedDeclarationsFunctionExpressionInCall.ts, 0, 39)) + + return Component; +>Component : Symbol(Component, Decl(isolatedDeclarationsFunctionExpressionInCall.ts, 3, 12)) + +}); + +export const arrowWithType = observer((): string => { +>arrowWithType : Symbol(arrowWithType, Decl(isolatedDeclarationsFunctionExpressionInCall.ts, 11, 12)) +>observer : Symbol(observer, Decl(isolatedDeclarationsFunctionExpressionInCall.ts, 0, 0)) + + return "typed"; +}); + +export const functionWithType = action(function (): typeof Component { +>functionWithType : Symbol(functionWithType, Decl(isolatedDeclarationsFunctionExpressionInCall.ts, 15, 12)) +>action : Symbol(action, Decl(isolatedDeclarationsFunctionExpressionInCall.ts, 0, 39)) +>Component : Symbol(Component, Decl(isolatedDeclarationsFunctionExpressionInCall.ts, 3, 12)) + + return Component; +>Component : Symbol(Component, Decl(isolatedDeclarationsFunctionExpressionInCall.ts, 3, 12)) + +}); diff --git a/tests/baselines/reference/isolatedDeclarationsFunctionExpressionInCall.types b/tests/baselines/reference/isolatedDeclarationsFunctionExpressionInCall.types new file mode 100644 index 0000000000000..a56d8aa414490 --- /dev/null +++ b/tests/baselines/reference/isolatedDeclarationsFunctionExpressionInCall.types @@ -0,0 +1,80 @@ +//// [tests/cases/compiler/isolatedDeclarationsFunctionExpressionInCall.ts] //// + +=== isolatedDeclarationsFunctionExpressionInCall.ts === +declare function observer(fn: T): T; +>observer : (fn: T) => T +> : ^ ^^ ^^ ^^^^^ +>fn : T +> : ^ + +declare function action(fn: T): T; +>action : (fn: T) => T +> : ^ ^^ ^^ ^^^^^ +>fn : T +> : ^ + +export const Component = observer(() => { +>Component : () => "hello" +> : ^^^^^^^^^^^^^ +>observer(() => { return "hello";}) : () => "hello" +> : ^^^^^^^^^^^^^ +>observer : (fn: T) => T +> : ^ ^^ ^^ ^^^^^ +>() => { return "hello";} : () => "hello" +> : ^^^^^^^^^^^^^ + + return "hello"; +>"hello" : "hello" +> : ^^^^^^^ + +}); + +export const thing = action(function () { +>thing : () => () => "hello" +> : ^^^^^^^^^^^^^^^^^^^ +>action(function () { return Component;}) : () => () => "hello" +> : ^^^^^^^^^^^^^^^^^^^ +>action : (fn: T) => T +> : ^ ^^ ^^ ^^^^^ +>function () { return Component;} : () => () => "hello" +> : ^^^^^^^^^^^^^^^^^^^ + + return Component; +>Component : () => "hello" +> : ^^^^^^^^^^^^^ + +}); + +export const arrowWithType = observer((): string => { +>arrowWithType : () => string +> : ^^^^^^ +>observer((): string => { return "typed";}) : () => string +> : ^^^^^^ +>observer : (fn: T) => T +> : ^ ^^ ^^ ^^^^^ +>(): string => { return "typed";} : () => string +> : ^^^^^^ + + return "typed"; +>"typed" : "typed" +> : ^^^^^^^ + +}); + +export const functionWithType = action(function (): typeof Component { +>functionWithType : () => typeof Component +> : ^^^^^^ +>action(function (): typeof Component { return Component;}) : () => typeof Component +> : ^^^^^^ +>action : (fn: T) => T +> : ^ ^^ ^^ ^^^^^ +>function (): typeof Component { return Component;} : () => typeof Component +> : ^^^^^^ +>Component : () => "hello" +> : ^^^^^^^^^^^^^ + + return Component; +>Component : () => "hello" +> : ^^^^^^^^^^^^^ + +}); diff --git a/tests/cases/compiler/isolatedDeclarationsFunctionExpressionInCall.ts b/tests/cases/compiler/isolatedDeclarationsFunctionExpressionInCall.ts new file mode 100644 index 0000000000000..514a9813e6772 --- /dev/null +++ b/tests/cases/compiler/isolatedDeclarationsFunctionExpressionInCall.ts @@ -0,0 +1,21 @@ +// @isolatedDeclarations: true +// @declaration: true + +declare function observer(fn: T): T; +declare function action(fn: T): T; + +export const Component = observer(() => { + return "hello"; +}); + +export const thing = action(function () { + return Component; +}); + +export const arrowWithType = observer((): string => { + return "typed"; +}); + +export const functionWithType = action(function (): typeof Component { + return Component; +}); \ No newline at end of file