From 113640e9742acb3a193078e9704648517aebf1d8 Mon Sep 17 00:00:00 2001 From: Josh Goldberg Date: Thu, 9 Feb 2023 22:30:24 -0500 Subject: [PATCH] feat(eslint-plugin): [explicit-function-return-type] add allowFunctionsWithoutTypeParameters option (#6105) --- .../rules/explicit-function-return-type.ts | 16 ++++- .../explicit-function-return-type.test.ts | 63 +++++++++++++++++++ 2 files changed, 76 insertions(+), 3 deletions(-) diff --git a/packages/eslint-plugin/src/rules/explicit-function-return-type.ts b/packages/eslint-plugin/src/rules/explicit-function-return-type.ts index 1d216ebff1d..9c91aa6d83d 100644 --- a/packages/eslint-plugin/src/rules/explicit-function-return-type.ts +++ b/packages/eslint-plugin/src/rules/explicit-function-return-type.ts @@ -15,6 +15,7 @@ type Options = [ allowHigherOrderFunctions?: boolean; allowDirectConstAssertionInArrowFunctions?: boolean; allowConciseArrowFunctionExpressionsStartingWithVoid?: boolean; + allowFunctionsWithoutTypeParameters?: boolean; allowedNames?: string[]; }, ]; @@ -61,6 +62,11 @@ export default util.createRule({ 'Whether to ignore arrow functions immediately returning a `as const` value.', type: 'boolean', }, + allowFunctionsWithoutTypeParameters: { + description: + "Whether to ignore functions that don't have generic type parameters.", + type: 'boolean', + }, allowedNames: { description: 'An array of function/method names that will not have their arguments or return values checked.', @@ -86,12 +92,16 @@ export default util.createRule({ ], create(context, [options]) { const sourceCode = context.getSourceCode(); - function isAllowedName( + function isAllowedFunction( node: | TSESTree.ArrowFunctionExpression | TSESTree.FunctionExpression | TSESTree.FunctionDeclaration, ): boolean { + if (options.allowFunctionsWithoutTypeParameters && !node.typeParameters) { + return true; + } + if (!options.allowedNames?.length) { return false; } @@ -153,7 +163,7 @@ export default util.createRule({ return; } - if (isAllowedName(node)) { + if (isAllowedFunction(node)) { return; } @@ -174,7 +184,7 @@ export default util.createRule({ ); }, FunctionDeclaration(node): void { - if (isAllowedName(node)) { + if (isAllowedFunction(node)) { return; } if (options.allowTypedFunctionExpressions && node.returnType) { diff --git a/packages/eslint-plugin/tests/rules/explicit-function-return-type.test.ts b/packages/eslint-plugin/tests/rules/explicit-function-return-type.test.ts index 40c15a89a2f..912242247af 100644 --- a/packages/eslint-plugin/tests/rules/explicit-function-return-type.test.ts +++ b/packages/eslint-plugin/tests/rules/explicit-function-return-type.test.ts @@ -400,6 +400,46 @@ new Foo(1, () => {}); code: 'const log = (message: string) => void console.log(message);', options: [{ allowConciseArrowFunctionExpressionsStartingWithVoid: true }], }, + { + code: 'const log = (a: string) => a;', + options: [{ allowFunctionsWithoutTypeParameters: true }], + }, + { + code: 'const log = (a: A): A => a;', + options: [{ allowFunctionsWithoutTypeParameters: true }], + }, + { + code: ` +function log(a: A): A { + return a; +} + `, + options: [{ allowFunctionsWithoutTypeParameters: true }], + }, + { + code: ` +function log(a: string) { + return a; +} + `, + options: [{ allowFunctionsWithoutTypeParameters: true }], + }, + { + code: ` +const log = function (a: A): A { + return a; +}; + `, + options: [{ allowFunctionsWithoutTypeParameters: true }], + }, + { + code: ` +const log = function (a: A): string { + return a; +}; + `, + options: [{ allowFunctionsWithoutTypeParameters: true }], + }, { filename: 'test.ts', options: [ @@ -1319,6 +1359,29 @@ const func = (value: number) => ({ type: 'X', value } as const); }, ], }, + { + code: 'const log = (a: A) => a;', + errors: [{ messageId: 'missingReturnType' }], + options: [{ allowFunctionsWithoutTypeParameters: true }], + }, + { + code: ` +function log(a: A) { + return a; +} + `, + errors: [{ messageId: 'missingReturnType' }], + options: [{ allowFunctionsWithoutTypeParameters: true }], + }, + { + code: ` +const log = function (a: A) { + return a; +}; + `, + errors: [{ messageId: 'missingReturnType' }], + options: [{ allowFunctionsWithoutTypeParameters: true }], + }, { filename: 'test.ts', options: [