diff --git a/packages/eslint-plugin/src/rules/no-misused-promises.ts b/packages/eslint-plugin/src/rules/no-misused-promises.ts index 9edd31141e0a..dd219fa95d3f 100644 --- a/packages/eslint-plugin/src/rules/no-misused-promises.ts +++ b/packages/eslint-plugin/src/rules/no-misused-promises.ts @@ -743,6 +743,20 @@ function checkThenableOrVoidArgument( ) { voidReturnIndices.add(index); } + const contextualType = checker.getContextualTypeForArgumentAtIndex( + node, + index, + ); + if (contextualType !== type) { + checkThenableOrVoidArgument( + checker, + node, + contextualType, + index, + thenableReturnIndices, + voidReturnIndices, + ); + } } // Get the positions of arguments which are void functions (and not also diff --git a/packages/eslint-plugin/tests/rules/no-misused-promises.test.ts b/packages/eslint-plugin/tests/rules/no-misused-promises.test.ts index 0c6b33582825..0f4330f890ca 100644 --- a/packages/eslint-plugin/tests/rules/no-misused-promises.test.ts +++ b/packages/eslint-plugin/tests/rules/no-misused-promises.test.ts @@ -1051,6 +1051,21 @@ interface MyInterface extends MyCall, MyIndex, MyConstruct, MyMethods { const array: number[] = [1, 2, 3]; array.filter(a => a > 1); `, + ` +type ReturnsPromiseVoid = () => Promise; +declare const useCallback: unknown>( + fn: T, +) => T; +useCallback(async () => {}); + `, + ` +type ReturnsVoid = () => void; +type ReturnsPromiseVoid = () => Promise; +declare const useCallback: unknown>( + fn: T, +) => T; +useCallback(async () => {}); + `, ], invalid: [ @@ -2322,5 +2337,97 @@ tuple.find(() => Promise.resolve(false)); }, ], }, + { + code: ` +type ReturnsVoid = () => void; +declare const useCallback: unknown>( + fn: T, +) => T; +declare const useCallbackReturningVoid: typeof useCallback; +useCallbackReturningVoid(async () => {}); + `, + errors: [ + { + line: 7, + messageId: 'voidReturnArgument', + }, + ], + }, + { + code: ` +type ReturnsVoid = () => void; +declare const useCallback: unknown>( + fn: T, +) => T; +useCallback(async () => {}); + `, + errors: [ + { + line: 6, + messageId: 'voidReturnArgument', + }, + ], + }, + { + code: ` +interface Foo { + (callback: () => T): void; + (callback: () => number): void; +} +declare const foo: Foo; + +foo(async () => {}); + `, + errors: [ + { + line: 8, + messageId: 'voidReturnArgument', + }, + ], + }, + { + code: ` +declare function tupleFn unknown>( + ...fns: [T, string, T] +): void; +tupleFn<() => void>( + async () => {}, + 'foo', + async () => {}, +); + `, + errors: [ + { + line: 6, + messageId: 'voidReturnArgument', + }, + { + line: 8, + messageId: 'voidReturnArgument', + }, + ], + }, + { + code: ` +declare function arrayFn unknown>( + ...fns: (T | string)[] +): void; +arrayFn<() => void>( + async () => {}, + 'foo', + async () => {}, +); + `, + errors: [ + { + line: 6, + messageId: 'voidReturnArgument', + }, + { + line: 8, + messageId: 'voidReturnArgument', + }, + ], + }, ], }); 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