-
-
Notifications
You must be signed in to change notification settings - Fork 2.7k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[no-misused-promises] Not marking as error when combined with a logical operator variable #2544
Comments
The rule doesn't do any sophisticated inspection - it just looks for a In this instance. // This correctly not marks a bad usage
if (localFalse && myPromise) { // typeof === false - hence it doesn't detect it
console.log("Bad usage");
}
// This should show a bad usage
if (parameterConditional && myPromise) { // typeof = false & Promise<boolean> - hence it doesn't detect it
console.log("Bad usage");
}
// This should show a bad usage
if (this.returnTrue() && myPromise) { // ditto - false & Promise
console.log("Bad usage");
} Happy to accept a PR to make the rule smarter! |
I don't think this is a matter of "the rule just isn't sophisticated enough", the rule specifically checks that all union parts are then-able: // Variation on the thenable check which requires all forms of the type (read:
// alternates in a union) to be thenable. Otherwise, you might be trying to
// check if something is defined or undefined and get caught because one of the
// branches is thenable.
function isAlwaysThenable(checker: ts.TypeChecker, node: ts.Node): boolean {
...
// If one of the alternates has no then property, it is not thenable in all
// cases.
if (thenProp === undefined) {
return false;
} I'm not sure what the correct logic should be, some options are:
also minor note, this can be simplified at the same time: - UnaryExpression(node) {
+ 'UnaryExpression[operator="!"]'(node: TSESTree.UnaryExpression) {
- if (node.operator === '!') {
checkConditional(node.argument);
- }
}, |
The issue here is that the rule does not properly analyse logical expressions within a conditional test context - it's not being sophisticated enough. It does do some checks on
However with this simple logic, it does not work well for all cases. Imagine the following code: async function foo(arg: false | Promise<boolean>) {
if (arg) {
return await arg;
}
} Is this a misused promise? The answer is no - you need to use the conditional to narrow the type first. So the rule correctly handles this. However if I do this: async function foo(bool: boolean, prom: Promise<boolean>) {
if (bool && prom) {
return await prom;
}
} Is this a misused promise? The answer is yes - it's an unnecessary condition AND it's a misused promise. The rule right now does not deeply inspect the logical - just the result of the logical. One final example to further drive the point home: async function foo(bool: true, prom: Promise<boolean>) {
if (bool || prom) {
return await prom;
}
} Is this a misused promise? The answer is yes - again it's an unnecessary condition AND it's a misused promise. The rule is not doing any sophisticated checks - it's just doing a naive check of the logical expression. It's checking the runtime value of the logical and ignoring the code itself. So the fix here is as follows: In a conditional test context the rule should deeply inspect a LogicalExpression and individually test each and every expression separately. |
I am working this |
Thank you so much for your help with this =) |
Repro
Expected Result
These lines should mark the promise as misused, but as they are applied an AND with an unknown boolean parameter or function result, they don't:Actual Result
Those lines are not marked as misuses of the promise but they are.
Additional Info
Versions
@typescript-eslint/eslint-plugin
4.1.0
@typescript-eslint/parser
4.1.0
TypeScript
3.9.7
ESLint
7.8.1
node
12.8.3
The text was updated successfully, but these errors were encountered: