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

[strict-boolean-expressions] Allow any #754

Closed
glen-84 opened this issue Jul 24, 2019 · 6 comments
Closed

[strict-boolean-expressions] Allow any #754

glen-84 opened this issue Jul 24, 2019 · 6 comments
Labels
enhancement: plugin rule option New rule option for an existing eslint-plugin rule good first issue Good for newcomers has pr there is a PR raised to close this package: eslint-plugin Issues related to @typescript-eslint/eslint-plugin

Comments

@glen-84
Copy link
Contributor

glen-84 commented Jul 24, 2019

Repro

{
  "rules": {
    "@typescript-eslint/strict-boolean-expressions": "error"
  }
}
const x: any;

if (x) {}

Expected Result

No error (at least with an option).

Actual Result

Error: Unexpected non-boolean in conditional.

Additional Info

TSLint seems to ignore any.

Implementation choices:

  • Ignore any always (should rather be handled by no implicit/explicit any)
  • Option allowAny, defaulting to true.
  • Option allowAny, defaulting to false.

Versions

package version
@typescript-eslint/eslint-plugin 1.13.0
@typescript-eslint/parser 1.13.0
TypeScript 3.4.5
ESLint 6.1.0
node 10.16.0
npm 6.9.0
@glen-84 glen-84 added package: eslint-plugin Issues related to @typescript-eslint/eslint-plugin triage Waiting for maintainers to take a look labels Jul 24, 2019
@bradzacher
Copy link
Member

bradzacher commented Jul 24, 2019

We're not looking for exact 1:1 compatibility with tslint, because as a system that's grown and evolved over time, not every feature/flag is needed, nor are they necessarily a good idea..

IMO this is working as expected right now - you're passing a non-boolean value into a place that's expecting a boolean.

Ignore any always (should rather be handled by no implicit/explicit any)

nope. it's too easy to accidentally fall into a place that has an any type. This could happen easily esp when consuming library types. Also in some cases things can become any for a variety of reasons.

Option allowAny, defaulting to true.

nope for the same reasons.

Option allowAny, defaulting to false.

This could work, sure. We need to add some options to the rule anyways because it's very, very strict without any options.

@bradzacher bradzacher added enhancement: plugin rule option New rule option for an existing eslint-plugin rule good first issue Good for newcomers and removed triage Waiting for maintainers to take a look good first issue Good for newcomers labels Jul 24, 2019
@glen-84
Copy link
Contributor Author

glen-84 commented Jul 25, 2019

We're not looking for exact 1:1 compatibility with tslint, because as a system that's grown and evolved over time, not every feature/flag is needed, nor are they necessarily a good idea..

I respect that, but it can mean that someone who has relied on certain functionality will now have to stop using the rule as it would potentially flag thousands of new issues.

(In this specific case, that doesn't apply to me, as I had not yet started using the equivalent TSLint rule.)

IMO this is working as expected right now - you're passing a non-boolean value into a place that's expecting a boolean.

I don't know. That might be true for explicit any, but isn't implicit any more of a lack of a type, than a specific type?

i.e.

const x;

if (x) {} // `x` is implicitly `any`, so it doesn't really have an explicitly-set type.

nope. it's too easy to accidentally fall into a place that has an any type. This could happen easily esp when consuming library types. Also in some cases things can become any for a variety of reasons.

My point was that this would be flagged by noImplicitAny, so this rule would not need to concern itself with any, but I can see the case for an explicitly-set any.

We need to add some options to the rule anyways because it's very, very strict without any options.

Agreed.

@bradzacher bradzacher added the good first issue Good for newcomers label Jul 25, 2019
@bradzacher
Copy link
Member

That might be true for explicit any, but isn't implicit any more of a lack of a type, than a specific type

It is, but there's no distinction in the compiler. It's either reported with type any, or it's reported with a type. So either we always allow any, or we never allow any.

My point was that this would be flagged by noImplicitAny

Sure your specific case would be flagged by that case. But consider this case:

// someModule.d.ts
export const untyped: any;

// myFile.ts
import { untyped } from 'someModule';

if (untyped) {}

What happens here? noImplictAny will not catch this case, because the flag does not check 3rd-party type definitions.
Which is why the rule is correct.

noImplicitAny only errors for one thing - when the user defines a variable without a type (i.e. implicitly defining any). But it doesn't stop explicit any, or any caused by things like // @ts-ignore

// eslint-disable-next-line @typescript-eslint/no-explicit-any
type MyRecord = { foo: any, bar: number }
declare const x: MyRecord;

const y = x.foo; // typed as any
// @ts-ignore
const z = x.baz; // typed as any

Which is why the default behaviour of blocking any is correct. The compiler is very good at allowing anys get around the place, if you're not careful.

I respect that, but it can mean that someone who has relied on certain functionality will now have to stop using the rule as it would potentially flag thousands of new issues.

Yeah I know - it means that it can take a little bit for these new rules to become adopted.
But it lets us figure out what should be the default behaviour, and what should be added as an option, etc, without doing the up front work of adding 8 options which might not get used. As people ask for them we can assess and add the flags in. Which means we end up with the minimal set of code, instead of a bloated 1:1 implementation.

Also it gives us the opportunity to merge options together. I.e. we might look and go "you'd never use flag X without flag Y, so lets add 1 options instead".

@phaux
Copy link
Contributor

phaux commented Sep 5, 2019

@glen-84 This rule is about being explicit and ignoring any would be against that. In case of any you should explicitly use if (Boolean(x)) {}

@glen-84
Copy link
Contributor Author

glen-84 commented Sep 7, 2019

@phaux,

This is about implicit any types, not explicit any types. For example, in projects that have not yet enabled noImplicitAny, and may be adding types incrementally.

In those cases, developers could benefit from if (string|number|etc.) being an error, while if (any) is ignored until the codebase is fully typed.

@bradzacher
Copy link
Member

This has been solved by #1631, which will be released in v3

@github-actions github-actions bot locked as resolved and limited conversation to collaborators Jun 11, 2020
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
enhancement: plugin rule option New rule option for an existing eslint-plugin rule good first issue Good for newcomers has pr there is a PR raised to close this package: eslint-plugin Issues related to @typescript-eslint/eslint-plugin
Projects
None yet
Development

Successfully merging a pull request may close this issue.

3 participants