Description
- I have tried restarting my IDE and the issue persists.
- I have updated to the latest version of the packages.
- I have read the FAQ and my problem is not listed.
- There is a similar issue ([no-floating-promises] Ability to ignore certain types from producing errors #2640) regarding ignoring certain Promise-like types, but it was closed. This proposal operates on a much more specific level: indicating that a particular async function will never raise an error
Repro
I have encountered some cases while cleaning up some old JS code for my company (and converting it to TS in the process) where I want to register a .then()
action on a Promise that I know will never be rejected. I don't want to have to use void whatever().then(...)
on every single instance where I am dealing with one of these promises, as they may be used very frequently and having to remember to put void
before every single usage of a non-rejecting promise is tedious (and ugly). I still want the warning to appear for promises that could be rejected, however, in case somebody forgets to handle an actual situation where a rejection might occur.
One specific example is in an AJAX helper method I created that will normalize any AJAX request (be it from one of our APIs or from an MVC backend), show an error message if it failed for some reason, or resolve a promise if it was successful. Here is some simplified pseudocode that should convey the general idea:
function sendAjaxAsync<Result = string>(options): Promise<Result> {
return new Promise<Result>(res => {
makeRequestAndNormalizeResponse(options).then(response => {
if (response.isSuccessful) {
res(response.result);
} else {
showErrorMessage(response.errorMessage);
}
});
});
}
let myButton = $("#myButton");
let myContainer = $("#myContainer");
myButton.on("click", () => sendAjaxAsync({ url: "/foo/bar/baz" }).then(html => myContainer.append(html)));
If the request succeeds, the HTML from the response will be appended to myContainer
. If it fails for some reason, sendAjaxAsync
will show an appropriate error message to the user, and the continuation will not run. There will be no runtime errors or rejections at all.
Another use case might be something like a wrapper around setTimeout
where the returned Promise is absolutely guaranteed to never reject ever, and it wouldn't even make sense to consider the possibility of a rejection:
// never rejects
function doSomething(): Promise<void> {
/* ... */
}
// never rejects
function waitFor(ms: number): Promise<void> {
return new Promise(res => setTimeout(res, ms));
}
let myButton = $("#myButton");
let myMessage = $("#myMessage");
myButton.on("click", () => {
doSomething()
.then(() => myMessage.show())
.then(() => waitFor(2000))
.then(() => myMessage.hide());
});
I'm sure there are plenty of other similar cases out there as well.
I am proposing a configuration rule such as the following to tell the no-floating-promises
rule that the Promise
returned by certain functions will NEVER be rejected so that a simple single-callback .then()
is enough for it to be treated as "not floating":
{
"rules": {
"@typescript-eslint/no-floating-promises": ["warn", {
"ignoredFunctions": [
"doSomething",
"waitFor"
]
}]
}
}
There may be a more elegant and/or flexible way of specifying this option; the example above is just one possibility.
Expected Result
I am expecting that, with the above hypothetical configuration, the example code would not have any linter warnings whatsoever.
Actual Result
Because no-floating-promises
currently assumes that every Promise
might be rejected, and thus must have a rejection handler registered 100% of the time, the above example raises a linter warning:
Additional Info
Versions
package | version |
---|---|
@typescript-eslint/eslint-plugin |
5.16.0 |
@typescript-eslint/parser |
5.16.0 |
TypeScript |
4.6.2 |
ESLint |
8.10.0 |
node |
16.12.0 |