Skip to content

[no-floating-promises] feature: does-not-throw annotation #3192

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

Closed
yury-s opened this issue Mar 16, 2021 · 2 comments
Closed

[no-floating-promises] feature: does-not-throw annotation #3192

yury-s opened this issue Mar 16, 2021 · 2 comments
Labels
package: eslint-plugin Issues related to @typescript-eslint/eslint-plugin wontfix This will not be worked on

Comments

@yury-s
Copy link

yury-s commented Mar 16, 2021

no-floating-promises rule currently supports to ways to suppress error: adding .catch to the promise and prepending void to the expression. In many cases it's known that returned Promise never throws and having to prepend all call sites with void just to suppress lint errors is tedious and impacts code readability. Rather than polluting all call sites with such annotations it'd be nice to have a marker on the async method/field telling lint that it never throws. Something like this:

class StringProvider {
  private _stringPromise: Promise<string>;
  _resolve: (s: string) => void = () => {};
  constructor() {
    this._stringPromise = new Promise(r => this._resolve = r);
  }

  // tslint:does-not-throw
  async string(): Promise<string> {
    return await this._stringPromise;
  }
}

function runWithString(provider: StringProvider) {
   provider.string().then(s => console.log('ready: ' + s));
}
@yury-s yury-s added package: eslint-plugin Issues related to @typescript-eslint/eslint-plugin triage Waiting for team members to take a look labels Mar 16, 2021
@bradzacher
Copy link
Member

Assessing comments is not something that we can do for a few reasons.

The rule does not assess that the method .string() returns a promise, it assesses that the expression statement provider.string().then(s => console.log('ready: ' + s)) returns a promise.
From there it then assesses that whether or not there is the required .catch handling on this expression statement.

So augmenting the rule to also assess not only that the promise came from .string(), but also that .string() is a method annotated with some comment is a huge change to the rule.

This change would be very computationally expensive to implement, as it would need to inspect more and more types. Types are lazily computed, which means more types = more time.

Additionally doing cross file source-code interrogation like this is expensive.
Given there's no way to know that a type is not annotated this way - that means we would have to check each and every method.
Which again - is a huge amount of computation.


Why not just use async/await?
That would solve your problem without any additional features in the rule, AND it would make your code cleaner.

async function runWithString(provider: StringProvider) {
  const s = await provider.string(); // no error here:
                                     // - the success case is handled
                                     // - the error case will throw
  console.log('ready: ' + s);
}

@bradzacher bradzacher added wontfix This will not be worked on and removed triage Waiting for team members to take a look labels Mar 16, 2021
@yury-s
Copy link
Author

yury-s commented Mar 16, 2021

Thanks for your detailed explanation, it all makes sense!

Why not just use async/await?
That would solve your problem without any additional features in the rule, AND it would make your code cleaner.

In the cases where it is ok to block the control flow in the method with await it is the best option, but there things where we don't want the main control flow to be blocked on that, i.e. we know that the promise will resolve at some point in the future and we want to chain an action to it but we also want to proceed with logic in the current method not waiting for that, here is an one example and another one. This can always be solved by adding .catch() or in some cases wrapping async call into a sync function like this:

function runWithString(provider: StringProvider) {
  provider.string().then(s => console.log('ready: ' + s), e => {}); // no error here:
}

This is just about the convenience of using the rule. The idea of method annotation popped up in a discussion of the trade-offs between the amount of noise introduced by the void and extra catch calls to enable the rule in our project and the actual benefits of having this rule always on (vs. running it manually every once in a while and fixing 'real' issues) so I decided to file it as a feature request.

@github-actions github-actions bot locked as resolved and limited conversation to collaborators Apr 16, 2021
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
package: eslint-plugin Issues related to @typescript-eslint/eslint-plugin wontfix This will not be worked on
Projects
None yet
Development

No branches or pull requests

2 participants