diff --git a/packages/eslint-plugin/src/rules/promise-function-async.ts b/packages/eslint-plugin/src/rules/promise-function-async.ts index 06fdd024c0e9..1739e1508937 100644 --- a/packages/eslint-plugin/src/rules/promise-function-async.ts +++ b/packages/eslint-plugin/src/rules/promise-function-async.ts @@ -23,7 +23,7 @@ export type Options = [ checkMethodDeclarations?: boolean; }, ]; -export type MessageIds = 'missingAsync'; +export type MessageIds = 'missingAsync' | 'missingAsyncHybridReturn'; export default createRule({ name: 'promise-function-async', @@ -37,6 +37,8 @@ export default createRule({ fixable: 'code', messages: { missingAsync: 'Functions that return promises must be async.', + missingAsyncHybridReturn: + 'Functions that return promises must be async. Consider adding an explicit return type annotation if the function is intended to return a union of promise and non-promise types.', }, schema: [ { @@ -164,10 +166,20 @@ export default createRule({ ), ) ) { + const isHybridReturnType = returnTypes.some( + type => + type.isUnion() && + !type.types.every(part => + containsAllTypesByName(part, true, allAllowedPromiseNames), + ), + ); + context.report({ loc: getFunctionHeadLoc(node, context.sourceCode), node, - messageId: 'missingAsync', + messageId: isHybridReturnType + ? 'missingAsyncHybridReturn' + : 'missingAsync', fix: fixer => { if ( node.parent.type === AST_NODE_TYPES.MethodDefinition || diff --git a/packages/eslint-plugin/tests/docs-eslint-output-snapshots/promise-function-async.shot b/packages/eslint-plugin/tests/docs-eslint-output-snapshots/promise-function-async.shot index 0c91850303e9..e85a8bf8c387 100644 --- a/packages/eslint-plugin/tests/docs-eslint-output-snapshots/promise-function-async.shot +++ b/packages/eslint-plugin/tests/docs-eslint-output-snapshots/promise-function-async.shot @@ -12,7 +12,7 @@ function functionReturnsPromise() { } function functionReturnsUnionWithPromiseImplicitly(p: boolean) { -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Functions that return promises must be async. +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Functions that return promises must be async. Consider adding an explicit return type annotation if the function is intended to return a union of promise and non-promise types. return p ? 'value' : Promise.resolve('value'); } " diff --git a/packages/eslint-plugin/tests/rules/promise-function-async.test.ts b/packages/eslint-plugin/tests/rules/promise-function-async.test.ts index 5ab4887334dc..da1999e93e82 100644 --- a/packages/eslint-plugin/tests/rules/promise-function-async.test.ts +++ b/packages/eslint-plugin/tests/rules/promise-function-async.test.ts @@ -825,7 +825,7 @@ function promiseInUnionWithoutExplicitReturnType(p: boolean) { `, errors: [ { - messageId, + messageId: 'missingAsyncHybridReturn', }, ], output: ` @@ -836,6 +836,65 @@ async function promiseInUnionWithoutExplicitReturnType(p: boolean) { }, { code: ` +function test1(): 'one' | Promise<'one'>; +function test1(a: number): Promise; +function test1(a?: number) { + if (a) { + return Promise.resolve(a); + } + + return Math.random() > 0.5 ? 'one' : Promise.resolve('one'); +} + `, + errors: [ + { + messageId: 'missingAsyncHybridReturn', + }, + ], + output: ` +function test1(): 'one' | Promise<'one'>; +function test1(a: number): Promise; +async function test1(a?: number) { + if (a) { + return Promise.resolve(a); + } + + return Math.random() > 0.5 ? 'one' : Promise.resolve('one'); +} + `, + }, + { + code: ` +class PromiseType { + s?: string; +} + +function promiseInUnionWithoutExplicitReturnType(p: boolean) { + return p ? new PromiseType() : 5; +} + `, + errors: [ + { + messageId: 'missingAsyncHybridReturn', + }, + ], + options: [ + { + allowedPromiseNames: ['PromiseType'], + }, + ], + output: ` +class PromiseType { + s?: string; +} + +async function promiseInUnionWithoutExplicitReturnType(p: boolean) { + return p ? new PromiseType() : 5; +} + `, + }, + { + code: ` function overloadingThatCanReturnPromise(): Promise; function overloadingThatCanReturnPromise(a: boolean): Promise; function overloadingThatCanReturnPromise( pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy