-
Notifications
You must be signed in to change notification settings - Fork 12.8k
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
Inverted Promise
should warn like it does without inverting
#46140
Comments
This should probably be predicated on the possibility that the awaited type of the Promise is falsy. I think we could look at this for uncalled functions too, since that shares most of the same code path. |
First case looks similar to #44840 |
Yeah, there are several issues asking us to be more aggressive about either recognizing code as unreachable or issuing errors when we already do (like hereβ Also related is #45267 |
One potential issue: narrowing to |
Any update? Just ran into this issue. Tried 4.6.4 and its still a problem. The bug I found today: ...
if (!isNameAvailable(name)) {
throw new MonkeyError(409, "Username already taken", name);
}
...
Removing the inversion highlights this error correctly: if (isNameAvailable(name)) {
Another interesting fact is that using if (!isNameAvailable(name) === true) {
But, as mentioned, the first code block is silently always false, causing headaches π |
Hey! We had a bug that would also have been caught by this. I started trying to implement a solution here: main...tjenkinson:TypeScript:support-condition-always-true-in-prefix-unary-expression Let me know if it looks like the right approach and I'll make it a PR and add some tests :) |
@tjenkinson It looks ok at a first glance. {
let fun!: () => void;
if (fun) { // Error
let x = 1;
}
}
{
let fun!: () => void;
if (fun) { // No error, because `fun` could actually be undefined and this is a valid check
let x = fun();
}
} For the negative case, the equivalent would be this: {
let fun!: () => void;
if (!fun) { // Should be error, probably a bug
// ...
}
}
{
let fun!: () => void;
if (!fun) { // Should not be error, `fun` could actually be undefined and this check is valid
// ...
}
else {
let x = fun();
}
} so your implementation would have to account for that. It would also be good to have more tests, for the other possible error and non-error cases for instance (e.g. unawaited promises), if you want to move forward with this. |
thanks @gabritto I'm wondering what the reasoning is behind ignoring when the variable is referenced in the block? Is it because there are a lot of cases in the wild where the types are wrong and therefore logic is guarded in if statements just in case? If that's the case I wonder if the same really applies when checking the inverse? If it does I guess we'd also need to allow code like let fun!: () => void;
if (!fun) {
throw new Error('`fun` missing');
}
fun(); which looks more complicated given the call is not part of the Wondering if when using I.e. let isEnabled!: () => Promise<boolean>;
// always error
if (!isEnabled()) {}
// always ok
if (!isEnabled) {} |
Yes.
We can start looking into that by creating a PR with the original version of your code (not doing anything special for promises or the negation case), and then I can run the extended tests on it to see if we need any special casing or not. |
Suggestion
π Search Terms
β Viability Checklist
My suggestion meets these guidelines:
β Suggestion
When checking the inverted truthyness if something returned from an
async
function without callingawait
, it should warn you you forgotawait
. This works without inverting.π Motivating Example
Playground
π» Use Cases
In my use, I had a function that returned a
User | undefined
and I was doing something if there wasn't a user returned. Later, I made the function async and forgot to update this since it was failing silently.The text was updated successfully, but these errors were encountered: