Skip to content

Commit

Permalink
feat(eslint-plugin): [restrict-plus-operands] add allow* options (#6161)
Browse files Browse the repository at this point in the history
* feat(eslint-plugin): [restrict-plus-operands] add allow* options from restrict-template-expressions

* Warn explicitly

* Update packages/eslint-plugin/docs/rules/restrict-plus-operands.md

Co-authored-by: Brad Zacher <brad.zacher@gmail.com>

* Brad suggestion

* Fix lint-markdown

---------

Co-authored-by: Brad Zacher <brad.zacher@gmail.com>
  • Loading branch information
JoshuaKGoldberg and bradzacher authored Jun 15, 2023
1 parent a91bb9e commit def09f8
Show file tree
Hide file tree
Showing 4 changed files with 975 additions and 340 deletions.
160 changes: 135 additions & 25 deletions packages/eslint-plugin/docs/rules/restrict-plus-operands.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,70 +18,180 @@ This rule reports when a `+` operation combines two values of different types, o
### ❌ Incorrect

```ts
var foo = '5.5' + 5;
var foo = 1n + 1;
let foo = '5.5' + 5;
let foo = 1n + 1;
```

### ✅ Correct

```ts
var foo = parseInt('5.5', 10) + 10;
var foo = 1n + 1n;
let foo = parseInt('5.5', 10) + 10;
let foo = 1n + 1n;
```

## Options

### `checkCompoundAssignments`
:::caution
We generally recommend against using these options, as they limit which varieties of incorrect `+` usage can be checked.
This in turn severely limits the validation that the rule can do to ensure that resulting strings and numbers are correct.

Safer alternatives to using the `allow*` options include:

- Using variadic forms of logging APIs to avoid needing to `+` values.
```ts
// Remove this line
console.log('The result is ' + true);
// Add this line
console.log('The result is', true);
```
- Using `.toFixed()` to coerce numbers to well-formed string representations:
```ts
const number = 1.123456789;
const result = 'The number is ' + number.toFixed(2);
// result === 'The number is 1.12'
```
- Calling `.toString()` on other types to mark explicit and intentional string coercion:
```ts
const arg = '11';
const regex = /[0-9]/;
const result =
'The result of ' +
regex.toString() +
'.test("' +
arg +
'") is ' +
regex.test(arg).toString();
// result === 'The result of /[0-9]/.test("11") is true'
```

:::

Examples of code for this rule with `{ checkCompoundAssignments: true }`:
### `allowAny`

Examples of code for this rule with `{ allowAny: true }`:

<!--tabs-->

#### ❌ Incorrect

```ts
/*eslint @typescript-eslint/restrict-plus-operands: ["error", { "checkCompoundAssignments": true }]*/
let fn = (a: number, b: []) => a + b;
let fn = (a: string, b: []) => a + b;
```

let foo: string | undefined;
foo += 'some data';
#### ✅ Correct

let bar: string = '';
bar += 0;
```ts
let fn = (a: number, b: any) => a + b;
let fn = (a: string, b: any) => a + b;
```

### `allowBoolean`

Examples of code for this rule with `{ allowBoolean: true }`:

<!--tabs-->

#### ❌ Incorrect

```ts
let fn = (a: number, b: unknown) => a + b;
let fn = (a: string, b: unknown) => a + b;
```

#### ✅ Correct

```ts
/*eslint @typescript-eslint/restrict-plus-operands: ["error", { "checkCompoundAssignments": true }]*/
let fn = (a: number, b: boolean) => a + b;
let fn = (a: string, b: boolean) => a + b;
```

let foo: number = 0;
foo += 1;
### `allowNullish`

let bar = '';
bar += 'test';
Examples of code for this rule with `{ allowNullish: true }`:

<!--tabs-->

#### ❌ Incorrect

```ts
let fn = (a: number, b: unknown) => a + b;
let fn = (a: number, b: never) => a + b;
let fn = (a: string, b: unknown) => a + b;
let fn = (a: string, b: never) => a + b;
```

### `allowAny`
#### ✅ Correct

Examples of code for this rule with `{ allowAny: true }`:
```ts
let fn = (a: number, b: undefined) => a + b;
let fn = (a: number, b: null) => a + b;
let fn = (a: string, b: undefined) => a + b;
let fn = (a: string, b: null) => a + b;
```

### `allowNumberAndString`

Examples of code for this rule with `{ allowNumberAndString: true }`:

<!--tabs-->

#### ❌ Incorrect

```ts
var fn = (a: any, b: boolean) => a + b;
var fn = (a: any, b: []) => a + b;
var fn = (a: any, b: {}) => a + b;
let fn = (a: number, b: unknown) => a + b;
let fn = (a: number, b: never) => a + b;
```

#### ✅ Correct

```ts
var fn = (a: any, b: any) => a + b;
var fn = (a: any, b: string) => a + b;
var fn = (a: any, b: bigint) => a + b;
var fn = (a: any, b: number) => a + b;
let fn = (a: number, b: string) => a + b;
let fn = (a: number, b: number | string) => a + b;
```

### `allowRegExp`

Examples of code for this rule with `{ allowRegExp: true }`:

<!--tabs-->

#### ❌ Incorrect

```ts
let fn = (a: number, b: RegExp) => a + b;
```

#### ✅ Correct

```ts
let fn = (a: string, b: RegExp) => a + b;
```

### `checkCompoundAssignments`

Examples of code for this rule with `{ checkCompoundAssignments: true }`:

<!--tabs-->

#### ❌ Incorrect

```ts
let foo: string | undefined;
foo += 'some data';
let bar: string = '';
bar += 0;
```

#### ✅ Correct

```ts
let foo: number = 0;
foo += 1;
let bar = '';
bar += 'test';
```

## When Not To Use It
Expand Down
Loading

0 comments on commit def09f8

Please sign in to comment.