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

feat(eslint-plugin): add strict-comparisons rule #314

1 change: 1 addition & 0 deletions packages/eslint-plugin/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -151,6 +151,7 @@ Then you should add `airbnb` (or `airbnb-base`) to your `extends` section of `.e
| [`@typescript-eslint/prefer-namespace-keyword`](./docs/rules/prefer-namespace-keyword.md) | Require the use of the `namespace` keyword instead of the `module` keyword to declare custom TypeScript modules. (`no-internal-module` from TSLint) | :heavy_check_mark: | :wrench: |
| [`@typescript-eslint/promise-function-async`](./docs/rules/promise-function-async.md) | Requires any function or method that returns a Promise to be marked async. (`promise-function-async` from TSLint) | :heavy_check_mark: | |
| [`@typescript-eslint/restrict-plus-operands`](./docs/rules/restrict-plus-operands.md) | When adding two variables, operands must both be of type number or of type string. (`restrict-plus-operands` from TSLint) | | |
| [`@typescript-eslint/strict-comparisons`](./docs/rules/strict-comparisons.md) | Only allow comparisons between primitive types. | | |
| [`@typescript-eslint/type-annotation-spacing`](./docs/rules/type-annotation-spacing.md) | Require consistent spacing around type annotations (`typedef-whitespace` from TSLint) | :heavy_check_mark: | :wrench: |
| [`@typescript-eslint/unified-signatures`](./docs/rules/unified-signatures.md) | Warns for any two overloads that could be unified into one. (`unified-signatures` from TSLint) | | |

Expand Down
89 changes: 89 additions & 0 deletions packages/eslint-plugin/docs/rules/strict-comparisons.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
# Only allow comparisons between primitive types. (strict-comparison)

This rule disallows comparisons between any non-primitive types. It also disables ordering comparisons between strings.

Using `>` `<` `>=` `<=` to compare strings is often a mistake, but can be allowed using the `allowStringOrderComparison` option.

By default, any comparisons between objects are not allowed. Objects are compared by reference, and in many cases this is not what
the developer wanted. This can be allowed by using the `allowObjectEqualComparison` option.

A couple of errors that would be caught by this rule:

<!-- prettier-ignore -->
```ts
if (true > false) {} // Not allowed
if (2 > undefined) {} // Not allowed
if ({} > {}) {} // Not allowed

if ('' > '') {} // This can be allowed by using the "allowStringOrderComparison" option.

// The following expressions are invalid by default, but can be allowed by using the "allowObjectEqualComparison" option
if ({} === {}) {} // Not allowed
if ([] === []) {} // Not allowed
if ({} === undefined) {} // Not allowed

const date1 = new Date(1550971894640)
const date2 = new Date(1550971894640)
if (date1 === date2) {} // Not allowed

function sameObject<T>(a: T, b: T): boolean {
return a === b; // Not allowed
}
```

## Rule Details

This rule aims to enforce typesafe comparisons.

## Options

This rule has an object option:

- `"allowObjectEqualComparison": false`, allows `!=` `==` `!==` `===` comparison between objects.
- `"allowStringOrderComparison": false`, allows `>` `<` `>=` `<=` comparison between strings.

### defaults

Examples of **incorrect** code for this rule with no options:

<!-- prettier-ignore -->
```ts
const object1 = {};
const object2 = {};

if (object1 === object2) {} // Not allowed to compare objects by reference without "allowObjectEqualComparison" option.
if (object1 > object2) {} // Not allowed to compare objects using an ordering operator.
```

Examples of **correct** code for this rule with no options at all:

<!-- prettier-ignore -->
```ts
const object1 = {};
const object2 = {};
if (isEqual(object1, object2)) {}
```

### allowObjectEqualComparison

Examples of **correct** code for this rule with `{ "allowObjectEqualComparison": true }`:

<!-- prettier-ignore -->
```ts
const object1 = {};
const object2 = {};
if (object1 === object2) {}
```

### allowStringOrderComparison

Examples of **correct** code for this rule with `{ "allowStringOrderComparison": true }` options:

<!-- prettier-ignore -->
```ts
if ('a' < 'b') {}
```

## When Not To Use It

If you know you want to compare objects by reference, you can safely turn this rule off.
Loading