From 58db655133aaae006efe3e3ceee971cf88dc348f Mon Sep 17 00:00:00 2001 From: Brad Zacher Date: Wed, 3 Jun 2020 11:00:27 -0700 Subject: [PATCH] fix(eslint-plugin): [explicit-module-boundary-types] handle bodyless arrow functions with explicit return types that return functions (#2169) --- .../rules/explicit-module-boundary-types.ts | 7 ++---- .../src/util/explicitReturnTypeUtils.ts | 25 ++++++------------- .../explicit-module-boundary-types.test.ts | 6 +++++ 3 files changed, 16 insertions(+), 22 deletions(-) diff --git a/packages/eslint-plugin/src/rules/explicit-module-boundary-types.ts b/packages/eslint-plugin/src/rules/explicit-module-boundary-types.ts index 2c065eb6212..fe4dbf28662 100644 --- a/packages/eslint-plugin/src/rules/explicit-module-boundary-types.ts +++ b/packages/eslint-plugin/src/rules/explicit-module-boundary-types.ts @@ -402,7 +402,7 @@ export default util.createRule({ if ( isAllowedName(node.parent) || isTypedFunctionExpression(node, options) || - ancestorHasReturnType(node.parent, options) + ancestorHasReturnType(node.parent) ) { return; } @@ -424,10 +424,7 @@ export default util.createRule({ } checkedFunctions.add(node); - if ( - isAllowedName(node.parent) || - ancestorHasReturnType(node.parent, options) - ) { + if (isAllowedName(node.parent) || ancestorHasReturnType(node.parent)) { return; } diff --git a/packages/eslint-plugin/src/util/explicitReturnTypeUtils.ts b/packages/eslint-plugin/src/util/explicitReturnTypeUtils.ts index 473a9d1549f..6c9c76645ac 100644 --- a/packages/eslint-plugin/src/util/explicitReturnTypeUtils.ts +++ b/packages/eslint-plugin/src/util/explicitReturnTypeUtils.ts @@ -300,10 +300,8 @@ function isValidFunctionExpressionReturnType( function isValidFunctionReturnType( node: FunctionNode, options: Options, - isParentCheck = false, ): boolean { if ( - !isParentCheck && options.allowHigherOrderFunctions && doesImmediatelyReturnFunctionExpression(node) ) { @@ -353,29 +351,22 @@ function checkFunctionExpressionReturnType( * Check whether any ancestor of the provided node has a valid return type, with * the given options. */ -function ancestorHasReturnType( - ancestor: TSESTree.Node | undefined, - options: Options, -): boolean { - // Exit early if this ancestor is not a ReturnStatement. - if (ancestor?.type !== AST_NODE_TYPES.ReturnStatement) { +function ancestorHasReturnType(ancestor: TSESTree.Node | undefined): boolean { + // if the ancestor is not a return, then this function was not returned at all, so we can exit early + const isReturnStatne = ancestor?.type === AST_NODE_TYPES.ReturnStatement; + const isBodylessArrow = + ancestor?.type === AST_NODE_TYPES.ArrowFunctionExpression && + ancestor.body.type !== AST_NODE_TYPES.BlockStatement; + if (!isReturnStatne && !isBodylessArrow) { return false; } - // This boolean tells the `isValidFunctionReturnType` that it is being called - // by an ancestor check. - const isParentCheck = true; - while (ancestor) { switch (ancestor.type) { case AST_NODE_TYPES.ArrowFunctionExpression: case AST_NODE_TYPES.FunctionExpression: - return ( - isValidFunctionExpressionReturnType(ancestor, options) || - isValidFunctionReturnType(ancestor, options, isParentCheck) - ); case AST_NODE_TYPES.FunctionDeclaration: - return isValidFunctionReturnType(ancestor, options, isParentCheck); + return ancestor.returnType != null; } ancestor = ancestor.parent; diff --git a/packages/eslint-plugin/tests/rules/explicit-module-boundary-types.test.ts b/packages/eslint-plugin/tests/rules/explicit-module-boundary-types.test.ts index 74efa619d90..44aa3c3d066 100644 --- a/packages/eslint-plugin/tests/rules/explicit-module-boundary-types.test.ts +++ b/packages/eslint-plugin/tests/rules/explicit-module-boundary-types.test.ts @@ -618,6 +618,12 @@ export function foo(...[a]: any): void {} ` export function foo(arg = 1): void {} `, + // https://github.com/typescript-eslint/typescript-eslint/issues/2161 + { + code: ` +export const foo = (): ((n: number) => string) => n => String(n); + `, + }, ], invalid: [ {