-
-
Notifications
You must be signed in to change notification settings - Fork 2.8k
Rule proposal: Warn when await keyword might be missing #4553
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
Comments
What's a good heuristic for "might be missing"? Your particular example can be shot down today with the It's not totally uncommon to generate a promise without immediately awaiting it, because you may want to |
The problem with pure JS is that you don't have a typed function boundary - so you can easily mess up invisibly. There is no one rule that handles this, there are a number which do handle this.
Josh is also right that you can't just warn on an unawaited promise anywhere because there's noting logically wrong with it. It's perfectly valid to assign and use later, or to pass to a function which in turn itself awaits. |
I've been severely burned on a project using Playwright, where I forgot to The problem was very difficult to identify and it's exactly the sort of thing I'd hope a linter would help with. On this project, I would have rather the linter complained and made me manually ignore false positives - that way, I would be actively making the decision, avoiding the risk of forgetting an await that causes a race condition. The cost of doing that is far less than the time we spent trying to isolate and identify the issue - it's very, very difficult to isolate an error that only occurs 1 out of 5 times, and only a specific system that isn't set up for debugging. Maybe this is not an inspection for everyone, and not an inspection for every project - projects aren't all the same, and that's why linters are configurable, right? It's definitely something that would help with Playwright projects, and probably others. I looked through the list of inspections suggested by @bradzacher above - I don't see how these, or any combination of these, would help.
I don't think we need to require await everywhere to get a useful inspection for this kind of issue. So ignore for a minute the example I cross-posted from the original eslint request. If I had to suggest the simplest possible inspection that would have caught this issue, I guess it would just need to check that you're doing something with a Promise. That is, if you create a Promise, or obtain one from a function call, the inspection would check that you're either assigning it to variable, returning it, awaiting it, or passing it. So this would be invalid: new Promise(resolve => { .... }); // ❌ no-unused-promise Returning a Promise would be valid: function createPromise() {
return new Promise(resolve => { .... }); // ✔ returned
}
createPromise(); // ❌ no-unused-promise This would be valid because it's assigned - but function stuff() {
const p = new Promise(resolve => { ... }); // ❌ no-unused-vars
} This would be valid because it's awaited: async function stuff() {
await new Promise(resolve => { ... }); // ✔ awaited
} And finally, passing the promise somewhere else would be valid: usePromise(new Promise(resolve => { ... })); // ✔ passed Again, if the call function doesn't do anything with that promise, function usePromise(p) {} // ❌ no-unused-vars The typical const $a = makePromiseA(); // ✔ assigned
const $b = makePromiseB(); // ✔ assigned
const [a, b] = await Promise.all([$a, $b]); // ✔ passed to Promise.all() As far as I can tell, no combination of existing inspections would have caught this issue - and |
@mindplay-dk all the examples you posted are violations under typescript-eslint/packages/eslint-plugin/tests/rules/no-floating-promises.test.ts Line 410 in 877cc48
Am I missing something? Note that the typescript-eslint playground is still pretty new and has some issues with typed rules and tsconfig lib settings. I set this up locally with...// index.ts
new Promise(resolve => { /* ... */ });
// Promises must be awaited, end with a call to .catch,
// end with a call to .then with a rejection handler or
// be explicitly marked as ignored with the `void` operator.
// eslint: @typescript-eslint/no-floating-promises
function createPromise() {
return new Promise(() => {
/* ... */
});
}
createPromise();
// Promises must be awaited, end with a call to .catch,
// end with a call to .then with a rejection handler or
// be explicitly marked as ignored with the `void` operator.
// eslint: @typescript-eslint/no-floating-promises // .eslintrc.js
module.exports = {
root: true,
parser: "@typescript-eslint/parser",
parserOptions: {
sourceType: "module",
project: ["./tsconfig.json"],
},
plugins: ["@typescript-eslint"],
rules: {
"@typescript-eslint/no-floating-promises": ["error"],
},
}; // tsconfig.json
{
"compilerOptions": {
"lib": ["esnext"],
"target": "esnext"
}
} |
Again - there's no one rule, but there are an assortment of rules you can use to enforce better standards in your codebase.
That's your perspective, and you're very much in the minority - for good reason. This is me speaking from experience at Meta. We have all manner of bad, custom, internal lint rules - many of which false positive. People just ignore them and add disable-comments. It actually trains people to start to completely ignore valid, known good lint rules as well. The same thing applies to type systems - false positive errors in the type system train people to ignore type system errors! |
Since this issue has gone two months without activity and is asking for something that seems to already exists, closing for housekeeping. Please file a new issue if you have a case not covered by existing rules. |
Sorry I didn't follow up - I left my job and didn't work on that project anymore. From the description and playground example it looks like you have these features, and I just wasn't finding them. I'm pretty thorough about reading documentation before submitting an issue - unfortunately, it's no longer fresh in my memory, so I can't say if there was something that could be improved. Sorry for taking up your time and thanks for looking into this. 🙂 |
Description
Add a rule that catches missing
await
, when the return-type of a function is aPromise
.This was previously proposed as an eslint feature, and rejected because:
However, as noted in the original issue:
There is some discussion in the original thread as to why TS itself doesn't type-check and help with this issue - as noted in the thread (before it was closed) the type-system does help when a return-value is assigned somewhere (to a variable or return-type declaration etc.) but I would add that it does not help when the return-type is
Promise<void>
.(Just to give an example of unavoidable side-effects which may require
Promise<void>
: I am working on a Playwright project, and the Playwright API heavily usesPromise<void>
to make sure you wait for side-effects you've requested by injecting things into the browser environment - this is just one example, I am sure there are many more, since e.g. DOM relies heavily on global state, side-effects and events.)Fail
An example was provided with the original eslint issue:
Pass
The text was updated successfully, but these errors were encountered: