Skip to content
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-throw-literal] proposal: optionally disallow throwing values of type any or unknown #4206

Closed
3 tasks done
hedgepigdaniel opened this issue Nov 23, 2021 · 7 comments
Closed
3 tasks done
Labels
accepting prs Go ahead, send a pull request that resolves this issue enhancement: plugin rule option New rule option for an existing eslint-plugin rule package: eslint-plugin Issues related to @typescript-eslint/eslint-plugin

Comments

@hedgepigdaniel
Copy link
Contributor

  • 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.

Repro

{
  "rules": {
    "@typescript-eslint/no-throw-literal": "error"
  }
}
function fun(value: any) {
  throw value;
}

function fun(value: unknown) {
  throw value;
}

Expected Result

I expect an error, because in both cases value does not have a type extending from Error.

Actual Result

No error

Additional Info

The docs state that the rule is called no-throw-literal for historical reasons (i.e. before it was aware of types). This is already an inaccurate name. I'd argue that the purpose of the rule is to prevent non-exceptions from being thrown, and therefore it should not be acceptable to throw any or unknown.

Versions

package version
@typescript-eslint/eslint-plugin 5.4.0
@hedgepigdaniel hedgepigdaniel added package: eslint-plugin Issues related to @typescript-eslint/eslint-plugin triage Waiting for maintainers to take a look labels Nov 23, 2021
@Josh-Cena
Copy link
Member

any extends Error. We probably need to treat any specially if people think that's a problem, but really by spec,

only allow expressions which have a possibility of being an Error object.

I take that as stating that throw e is accepted as long as typeof e is cross-assignable with Error? (i.e. supertypes are allowed as well)

@bradzacher
Copy link
Member

A big reason it allows these unknown types is because it's very common and easy to get into these states. For example this pattern is very common:

try {} catch (ex) {
  // Do something first...
  throw ex;
}

This pattern now no longer works with the option and instead you have to add a guard and handle the non-error case.

Esp for TS newbies - it is not uncommon for them to do something unsafe to shut the rule up like blindly using an as assertion.

function fn() {
  throw 'error';
}

try {
  fn();
} catch (ex) {
  // Unsafe and wrong
  throw ex as Error;
}

I'm not against options for additional strictness here - as long as they default to allowing any/unknown.

@bradzacher bradzacher added accepting prs Go ahead, send a pull request that resolves this issue enhancement: plugin rule option New rule option for an existing eslint-plugin rule and removed triage Waiting for maintainers to take a look labels Nov 23, 2021
@hedgepigdaniel
Copy link
Contributor Author

any extends Error

Yes I guess technically any extends everything, but I think it's reasonable in some projects to decide not to accept throwing it, and to instead to use accurate/specific types. I put separate options for any and unknown in #4207, so the user can decide how strict it is.

only allow expressions which have a possibility of being an Error object.

Is that from the description of the build in eslint no-throw-literal rule? My take on it is that the aim was to prevent throwing anything that wasn't actually an Error, but the best that could be done without type information was to prevent throwing a literal (the only syntactical thing that couldn't possibly be an Error).

This pattern now no longer works with the option and instead you have to add a guard and handle the non-error case.

Esp for TS newbies - it is not uncommon for them to do something unsafe to shut the rule up like blindly using an as assertion.
Yes agree, it's not a good idea to enable unless you do

True - its probably only useful for those who do want to add those guards and don't want to throw non Error values.

I'm not against options for additional strictness here - as long as they default to allowing any/unknown.

Sure - the options added in #4207 are disabled by default as you suggest.

@Josh-Cena
Copy link
Member

Is that from the description of the build in eslint no-throw-literal rule?

That's from the ts-eslint spec. https://typescript-eslint.io/rules/no-throw-literal

@hedgepigdaniel
Copy link
Contributor Author

Ah right - yes I updated the description in #4207 but not the title. Not sure if it's necessary or a good idea. The title is still accurate, just not a complete description of what it does (even now).

@guilhermesimoes
Copy link

I think this configuration goes hand in hand with @typescript-eslint/no-unsafe-return. any can be used sparingly, but we should have ways of preventing it from spreading to the rest of the codebase. We can already prevent any from being returned and, with this issue tackled, we should be able to prevent it from being thrown as well!

@manovotny
Copy link
Contributor

Should this be closed now that #4207 is merged?

@github-actions github-actions bot locked as resolved and limited conversation to collaborators Feb 11, 2022
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
accepting prs Go ahead, send a pull request that resolves this issue enhancement: plugin rule option New rule option for an existing eslint-plugin rule package: eslint-plugin Issues related to @typescript-eslint/eslint-plugin
Projects
None yet
Development

No branches or pull requests

5 participants