Skip to content

Commit 128d95b

Browse files
ronamiJoshuaKGoldbergkirkwaiblinger
authored
fix(eslint-plugin): [promise-function-async] use a different error message for functions with promise and non-promise types (#10950)
* initial implementation * tests * snapshots * cover overloading case * Update packages/eslint-plugin/src/rules/promise-function-async.ts Co-authored-by: Josh Goldberg ✨ <[email protected]> * snapshots * Update packages/eslint-plugin/src/rules/promise-function-async.ts Co-authored-by: Kirk Waiblinger <[email protected]> * snapshots --------- Co-authored-by: Josh Goldberg ✨ <[email protected]> Co-authored-by: Kirk Waiblinger <[email protected]>
1 parent fa265a9 commit 128d95b

File tree

3 files changed

+75
-4
lines changed

3 files changed

+75
-4
lines changed

Diff for: packages/eslint-plugin/src/rules/promise-function-async.ts

+14-2
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ export type Options = [
2323
checkMethodDeclarations?: boolean;
2424
},
2525
];
26-
export type MessageIds = 'missingAsync';
26+
export type MessageIds = 'missingAsync' | 'missingAsyncHybridReturn';
2727

2828
export default createRule<Options, MessageIds>({
2929
name: 'promise-function-async',
@@ -37,6 +37,8 @@ export default createRule<Options, MessageIds>({
3737
fixable: 'code',
3838
messages: {
3939
missingAsync: 'Functions that return promises must be async.',
40+
missingAsyncHybridReturn:
41+
'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.',
4042
},
4143
schema: [
4244
{
@@ -164,10 +166,20 @@ export default createRule<Options, MessageIds>({
164166
),
165167
)
166168
) {
169+
const isHybridReturnType = returnTypes.some(
170+
type =>
171+
type.isUnion() &&
172+
!type.types.every(part =>
173+
containsAllTypesByName(part, true, allAllowedPromiseNames),
174+
),
175+
);
176+
167177
context.report({
168178
loc: getFunctionHeadLoc(node, context.sourceCode),
169179
node,
170-
messageId: 'missingAsync',
180+
messageId: isHybridReturnType
181+
? 'missingAsyncHybridReturn'
182+
: 'missingAsync',
171183
fix: fixer => {
172184
if (
173185
node.parent.type === AST_NODE_TYPES.MethodDefinition ||

Diff for: packages/eslint-plugin/tests/docs-eslint-output-snapshots/promise-function-async.shot

+1-1
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Diff for: packages/eslint-plugin/tests/rules/promise-function-async.test.ts

+60-1
Original file line numberDiff line numberDiff line change
@@ -825,7 +825,7 @@ function promiseInUnionWithoutExplicitReturnType(p: boolean) {
825825
`,
826826
errors: [
827827
{
828-
messageId,
828+
messageId: 'missingAsyncHybridReturn',
829829
},
830830
],
831831
output: `
@@ -836,6 +836,65 @@ async function promiseInUnionWithoutExplicitReturnType(p: boolean) {
836836
},
837837
{
838838
code: `
839+
function test1(): 'one' | Promise<'one'>;
840+
function test1(a: number): Promise<number>;
841+
function test1(a?: number) {
842+
if (a) {
843+
return Promise.resolve(a);
844+
}
845+
846+
return Math.random() > 0.5 ? 'one' : Promise.resolve('one');
847+
}
848+
`,
849+
errors: [
850+
{
851+
messageId: 'missingAsyncHybridReturn',
852+
},
853+
],
854+
output: `
855+
function test1(): 'one' | Promise<'one'>;
856+
function test1(a: number): Promise<number>;
857+
async function test1(a?: number) {
858+
if (a) {
859+
return Promise.resolve(a);
860+
}
861+
862+
return Math.random() > 0.5 ? 'one' : Promise.resolve('one');
863+
}
864+
`,
865+
},
866+
{
867+
code: `
868+
class PromiseType {
869+
s?: string;
870+
}
871+
872+
function promiseInUnionWithoutExplicitReturnType(p: boolean) {
873+
return p ? new PromiseType() : 5;
874+
}
875+
`,
876+
errors: [
877+
{
878+
messageId: 'missingAsyncHybridReturn',
879+
},
880+
],
881+
options: [
882+
{
883+
allowedPromiseNames: ['PromiseType'],
884+
},
885+
],
886+
output: `
887+
class PromiseType {
888+
s?: string;
889+
}
890+
891+
async function promiseInUnionWithoutExplicitReturnType(p: boolean) {
892+
return p ? new PromiseType() : 5;
893+
}
894+
`,
895+
},
896+
{
897+
code: `
839898
function overloadingThatCanReturnPromise(): Promise<number>;
840899
function overloadingThatCanReturnPromise(a: boolean): Promise<string>;
841900
function overloadingThatCanReturnPromise(

0 commit comments

Comments
 (0)