@typescript-eslint/eslint-plugin 6.0.0-alpha.99 → 6.0.1-alpha.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +2 -0
- package/dist/configs/all.js +2 -0
- package/dist/configs/all.js.map +1 -1
- package/dist/configs/disable-type-checked.js +3 -0
- package/dist/configs/disable-type-checked.js.map +1 -1
- package/dist/configs/recommended-type-checked.js +6 -0
- package/dist/configs/recommended-type-checked.js.map +1 -1
- package/dist/configs/recommended.js +2 -0
- package/dist/configs/recommended.js.map +1 -1
- package/dist/configs/strict-type-checked.js +4 -0
- package/dist/configs/strict-type-checked.js.map +1 -1
- package/dist/configs/stylistic-type-checked.js +0 -1
- package/dist/configs/stylistic-type-checked.js.map +1 -1
- package/dist/configs/stylistic.js +0 -2
- package/dist/configs/stylistic.js.map +1 -1
- package/dist/index.js +1 -0
- package/dist/index.js.map +1 -1
- package/dist/rules/array-type.js +19 -20
- package/dist/rules/array-type.js.map +1 -1
- package/dist/rules/ban-ts-comment.js +33 -35
- package/dist/rules/ban-ts-comment.js.map +1 -1
- package/dist/rules/ban-types.js +75 -14
- package/dist/rules/ban-types.js.map +1 -1
- package/dist/rules/class-literal-property-style.js +38 -21
- package/dist/rules/class-literal-property-style.js.map +1 -1
- package/dist/rules/comma-dangle.js +4 -2
- package/dist/rules/comma-dangle.js.map +1 -1
- package/dist/rules/comma-spacing.js +5 -0
- package/dist/rules/comma-spacing.js.map +1 -1
- package/dist/rules/consistent-generic-constructors.js +1 -0
- package/dist/rules/consistent-generic-constructors.js.map +1 -1
- package/dist/rules/consistent-indexed-object-style.js +1 -0
- package/dist/rules/consistent-indexed-object-style.js.map +1 -1
- package/dist/rules/consistent-type-assertions.js +49 -0
- package/dist/rules/consistent-type-assertions.js.map +1 -1
- package/dist/rules/consistent-type-definitions.js +1 -0
- package/dist/rules/consistent-type-definitions.js.map +1 -1
- package/dist/rules/consistent-type-exports.js +1 -0
- package/dist/rules/consistent-type-exports.js.map +1 -1
- package/dist/rules/consistent-type-imports.js +2 -0
- package/dist/rules/consistent-type-imports.js.map +1 -1
- package/dist/rules/enum-utils/shared.js +61 -0
- package/dist/rules/enum-utils/shared.js.map +1 -0
- package/dist/rules/explicit-function-return-type.js.map +1 -1
- package/dist/rules/explicit-member-accessibility.js +43 -44
- package/dist/rules/explicit-member-accessibility.js.map +1 -1
- package/dist/rules/explicit-module-boundary-types.js +1 -1
- package/dist/rules/explicit-module-boundary-types.js.map +1 -1
- package/dist/rules/func-call-spacing.js +2 -0
- package/dist/rules/func-call-spacing.js.map +1 -1
- package/dist/rules/indent.js.map +1 -1
- package/dist/rules/index.js +4 -0
- package/dist/rules/index.js.map +1 -1
- package/dist/rules/key-spacing.js.map +1 -1
- package/dist/rules/keyword-spacing.js.map +1 -1
- package/dist/rules/lines-around-comment.js +78 -81
- package/dist/rules/lines-around-comment.js.map +1 -1
- package/dist/rules/lines-between-class-members.js +7 -5
- package/dist/rules/lines-between-class-members.js.map +1 -1
- package/dist/rules/member-delimiter-style.js +45 -27
- package/dist/rules/member-delimiter-style.js.map +1 -1
- package/dist/rules/member-ordering.js +55 -66
- package/dist/rules/member-ordering.js.map +1 -1
- package/dist/rules/method-signature-style.js +1 -0
- package/dist/rules/method-signature-style.js.map +1 -1
- package/dist/rules/naming-convention-utils/enums.js +6 -12
- package/dist/rules/naming-convention-utils/enums.js.map +1 -1
- package/dist/rules/naming-convention-utils/schema.js +50 -25
- package/dist/rules/naming-convention-utils/schema.js.map +1 -1
- package/dist/rules/naming-convention.js.map +1 -1
- package/dist/rules/no-base-to-string.js +2 -2
- package/dist/rules/no-base-to-string.js.map +1 -1
- package/dist/rules/no-confusing-void-expression.js +1 -0
- package/dist/rules/no-confusing-void-expression.js.map +1 -1
- package/dist/rules/no-duplicate-type-constituents.js +161 -0
- package/dist/rules/no-duplicate-type-constituents.js.map +1 -0
- package/dist/rules/no-empty-function.js +1 -0
- package/dist/rules/no-empty-function.js.map +1 -1
- package/dist/rules/no-empty-interface.js +2 -1
- package/dist/rules/no-empty-interface.js.map +1 -1
- package/dist/rules/no-explicit-any.js +1 -1
- package/dist/rules/no-explicit-any.js.map +1 -1
- package/dist/rules/no-extraneous-class.js +2 -3
- package/dist/rules/no-extraneous-class.js.map +1 -1
- package/dist/rules/no-implied-eval.js +1 -0
- package/dist/rules/no-implied-eval.js.map +1 -1
- package/dist/rules/no-inferrable-types.js.map +1 -1
- package/dist/rules/no-invalid-void-type.js +1 -1
- package/dist/rules/no-invalid-void-type.js.map +1 -1
- package/dist/rules/no-loop-func.js.map +1 -1
- package/dist/rules/no-magic-numbers.js.map +1 -1
- package/dist/rules/no-misused-promises.js +3 -2
- package/dist/rules/no-misused-promises.js.map +1 -1
- package/dist/rules/no-redeclare.js +2 -1
- package/dist/rules/no-redeclare.js.map +1 -1
- package/dist/rules/no-redundant-type-constituents.js +2 -0
- package/dist/rules/no-redundant-type-constituents.js.map +1 -1
- package/dist/rules/no-restricted-imports.js +80 -21
- package/dist/rules/no-restricted-imports.js.map +1 -1
- package/dist/rules/no-shadow.js +2 -1
- package/dist/rules/no-shadow.js.map +1 -1
- package/dist/rules/no-type-alias.js +24 -15
- package/dist/rules/no-type-alias.js.map +1 -1
- package/dist/rules/no-unnecessary-condition.js +2 -2
- package/dist/rules/no-unnecessary-condition.js.map +1 -1
- package/dist/rules/no-unnecessary-qualifier.js.map +1 -1
- package/dist/rules/no-unnecessary-type-assertion.js +1 -0
- package/dist/rules/no-unnecessary-type-assertion.js.map +1 -1
- package/dist/rules/no-unsafe-argument.js +3 -3
- package/dist/rules/no-unsafe-argument.js.map +1 -1
- package/dist/rules/no-unsafe-declaration-merging.js +1 -1
- package/dist/rules/no-unsafe-declaration-merging.js.map +1 -1
- package/dist/rules/no-unsafe-enum-comparison.js +119 -0
- package/dist/rules/no-unsafe-enum-comparison.js.map +1 -0
- package/dist/rules/no-unused-vars.js +4 -0
- package/dist/rules/no-unused-vars.js.map +1 -1
- package/dist/rules/no-use-before-define.js +1 -0
- package/dist/rules/no-use-before-define.js.map +1 -1
- package/dist/rules/padding-line-between-statements.js +11 -3
- package/dist/rules/padding-line-between-statements.js.map +1 -1
- package/dist/rules/parameter-properties.js +29 -30
- package/dist/rules/parameter-properties.js.map +1 -1
- package/dist/rules/prefer-includes.js +21 -5
- package/dist/rules/prefer-includes.js.map +1 -1
- package/dist/rules/prefer-nullish-coalescing.js +82 -63
- package/dist/rules/prefer-nullish-coalescing.js.map +1 -1
- package/dist/rules/prefer-optional-chain-utils/PreferOptionalChainOptions.js +3 -0
- package/dist/rules/prefer-optional-chain-utils/PreferOptionalChainOptions.js.map +1 -0
- package/dist/rules/prefer-optional-chain-utils/analyzeChain.js +419 -0
- package/dist/rules/prefer-optional-chain-utils/analyzeChain.js.map +1 -0
- package/dist/rules/prefer-optional-chain-utils/compareNodes.js +318 -0
- package/dist/rules/prefer-optional-chain-utils/compareNodes.js.map +1 -0
- package/dist/rules/prefer-optional-chain-utils/gatherLogicalOperands.js +281 -0
- package/dist/rules/prefer-optional-chain-utils/gatherLogicalOperands.js.map +1 -0
- package/dist/rules/prefer-optional-chain.js +80 -391
- package/dist/rules/prefer-optional-chain.js.map +1 -1
- package/dist/rules/prefer-readonly.js +1 -1
- package/dist/rules/prefer-readonly.js.map +1 -1
- package/dist/rules/prefer-regexp-exec.js +7 -1
- package/dist/rules/prefer-regexp-exec.js.map +1 -1
- package/dist/rules/require-array-sort-compare.js +3 -2
- package/dist/rules/require-array-sort-compare.js.map +1 -1
- package/dist/rules/restrict-plus-operands.js +132 -96
- package/dist/rules/restrict-plus-operands.js.map +1 -1
- package/dist/rules/restrict-template-expressions.js +11 -6
- package/dist/rules/restrict-template-expressions.js.map +1 -1
- package/dist/rules/return-await.js +1 -0
- package/dist/rules/return-await.js.map +1 -1
- package/dist/rules/sort-type-constituents.js +1 -1
- package/dist/rules/sort-type-constituents.js.map +1 -1
- package/dist/rules/space-before-function-paren.js +4 -0
- package/dist/rules/space-before-function-paren.js.map +1 -1
- package/dist/rules/strict-boolean-expressions.js +7 -2
- package/dist/rules/strict-boolean-expressions.js.map +1 -1
- package/dist/rules/switch-exhaustiveness-check.js.map +1 -1
- package/dist/rules/triple-slash-reference.js +3 -0
- package/dist/rules/triple-slash-reference.js.map +1 -1
- package/dist/rules/type-annotation-spacing.js +16 -14
- package/dist/rules/type-annotation-spacing.js.map +1 -1
- package/dist/rules/typedef.js +1 -0
- package/dist/rules/typedef.js.map +1 -1
- package/dist/rules/unbound-method.js +1 -0
- package/dist/rules/unbound-method.js.map +1 -1
- package/dist/rules/unified-signatures.js +3 -3
- package/dist/rules/unified-signatures.js.map +1 -1
- package/dist/util/astUtils.js.map +1 -1
- package/dist/util/collectUnusedVariables.js +1 -1
- package/dist/util/collectUnusedVariables.js.map +1 -1
- package/dist/util/getOperatorPrecedence.js +112 -2
- package/dist/util/getOperatorPrecedence.js.map +1 -1
- package/dist/util/getStringLength.js +2 -2
- package/dist/util/getStringLength.js.map +1 -1
- package/dist/util/misc.js +1 -2
- package/dist/util/misc.js.map +1 -1
- package/docs/rules/README.md +2 -2
- package/docs/rules/ban-types.md +10 -0
- package/docs/rules/comma-dangle.md +1 -1
- package/docs/rules/explicit-module-boundary-types.md +1 -1
- package/docs/rules/lines-around-comment.md +3 -13
- package/docs/rules/naming-convention.md +63 -63
- package/docs/rules/no-duplicate-type-constituents.md +61 -0
- package/docs/rules/no-unnecessary-boolean-literal-compare.md +10 -10
- package/docs/rules/no-unnecessary-type-constraint.md +6 -2
- package/docs/rules/no-unsafe-enum-comparison.md +77 -0
- package/docs/rules/prefer-includes.md +1 -1
- package/docs/rules/prefer-nullish-coalescing.md +23 -0
- package/docs/rules/prefer-optional-chain.md +195 -4
- package/docs/rules/require-await.md +0 -2
- package/docs/rules/restrict-plus-operands.md +135 -25
- package/docs/rules/restrict-template-expressions.md +15 -3
- package/docs/rules/sort-type-constituents.md +3 -3
- package/docs/rules/triple-slash-reference.md +0 -2
- package/docs/rules/type-annotation-spacing.md +22 -8
- package/docs/rules/unified-signatures.md +0 -2
- package/package.json +22 -15
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
---
|
|
2
|
+
description: 'Disallow duplicate constituents of union or intersection types.'
|
|
3
|
+
---
|
|
4
|
+
|
|
5
|
+
> 🛑 This file is source code, not the primary documentation location! 🛑
|
|
6
|
+
>
|
|
7
|
+
> See **https://typescript-eslint.io/rules/no-duplicate-type-constituents** for documentation.
|
|
8
|
+
|
|
9
|
+
TypeScript supports types ("constituents") within union and intersection types being duplicates of each other.
|
|
10
|
+
However, developers typically expect each constituent to be unique within its intersection or union.
|
|
11
|
+
Duplicate values make the code overly verbose and generally reduce readability.
|
|
12
|
+
|
|
13
|
+
## Rule Details
|
|
14
|
+
|
|
15
|
+
This rule disallows duplicate union or intersection constituents.
|
|
16
|
+
We consider types to be duplicate if they evaluate to the same result in the type system.
|
|
17
|
+
For example, given `type A = string` and `type T = string | A`, this rule would flag that `A` is the same type as `string`.
|
|
18
|
+
|
|
19
|
+
<!--tabs-->
|
|
20
|
+
|
|
21
|
+
### ❌ Incorrect
|
|
22
|
+
|
|
23
|
+
```ts
|
|
24
|
+
type T1 = 'A' | 'A';
|
|
25
|
+
|
|
26
|
+
type T2 = A | A | B;
|
|
27
|
+
|
|
28
|
+
type T3 = { a: string } & { a: string };
|
|
29
|
+
|
|
30
|
+
type T4 = [1, 2, 3] | [1, 2, 3];
|
|
31
|
+
|
|
32
|
+
type StringA = string;
|
|
33
|
+
type StringB = string;
|
|
34
|
+
type T5 = StringA | StringB;
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
### ✅ Correct
|
|
38
|
+
|
|
39
|
+
```ts
|
|
40
|
+
type T1 = 'A' | 'B';
|
|
41
|
+
|
|
42
|
+
type T2 = A | B | C;
|
|
43
|
+
|
|
44
|
+
type T3 = { a: string } & { b: string };
|
|
45
|
+
|
|
46
|
+
type T4 = [1, 2, 3] | [1, 2, 3, 4];
|
|
47
|
+
|
|
48
|
+
type StringA = string;
|
|
49
|
+
type NumberB = number;
|
|
50
|
+
type T5 = StringA | NumberB;
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
## Options
|
|
54
|
+
|
|
55
|
+
### `ignoreIntersections`
|
|
56
|
+
|
|
57
|
+
When set to true, duplicate checks on intersection type constituents are ignored.
|
|
58
|
+
|
|
59
|
+
### `ignoreUnions`
|
|
60
|
+
|
|
61
|
+
When set to true, duplicate checks on union type constituents are ignored.
|
|
@@ -115,16 +115,16 @@ if (!(someNullCondition ?? true)) {
|
|
|
115
115
|
|
|
116
116
|
## Fixer
|
|
117
117
|
|
|
118
|
-
|
|
|
119
|
-
|
|
|
120
|
-
|
|
|
121
|
-
|
|
|
122
|
-
|
|
|
123
|
-
|
|
|
124
|
-
|
|
|
125
|
-
|
|
|
126
|
-
|
|
|
127
|
-
|
|
|
118
|
+
| Comparison | Fixer Output | Notes |
|
|
119
|
+
| :-------------------------------: | ------------------------------- | ----------------------------------------------------------------------------------- |
|
|
120
|
+
| `booleanVar === true` | `booleanVar` | |
|
|
121
|
+
| `booleanVar !== true` | `!booleanVar` | |
|
|
122
|
+
| `booleanVar === false` | `!booleanVar` | |
|
|
123
|
+
| `booleanVar !== false` | `booleanVar` | |
|
|
124
|
+
| `nullableBooleanVar === true` | `nullableBooleanVar` | Only checked/fixed if the `allowComparingNullableBooleansToTrue` option is `false` |
|
|
125
|
+
| `nullableBooleanVar !== true` | `!nullableBooleanVar` | Only checked/fixed if the `allowComparingNullableBooleansToTrue` option is `false` |
|
|
126
|
+
| `!(nullableBooleanVar === false)` | `nullableBooleanVar ?? true` | Only checked/fixed if the `allowComparingNullableBooleansToFalse` option is `false` |
|
|
127
|
+
| `!(nullableBooleanVar !== false)` | `!(nullableBooleanVar ?? true)` | Only checked/fixed if the `allowComparingNullableBooleansToFalse` option is `false` |
|
|
128
128
|
|
|
129
129
|
## Not To Use It
|
|
130
130
|
|
|
@@ -7,8 +7,8 @@ description: 'Disallow unnecessary constraints on generic types.'
|
|
|
7
7
|
> See **https://typescript-eslint.io/rules/no-unnecessary-type-constraint** for documentation.
|
|
8
8
|
|
|
9
9
|
Generic type parameters (`<T>`) in TypeScript may be "constrained" with an [`extends` keyword](https://www.typescriptlang.org/docs/handbook/generics.html#generic-constraints).
|
|
10
|
-
When no `extends` is provided, type parameters default a constraint to `
|
|
11
|
-
It is therefore redundant to `extend` from `any`.
|
|
10
|
+
When no `extends` is provided, type parameters default a constraint to `unknown`.
|
|
11
|
+
It is therefore redundant to `extend` from `any` or `unknown`.
|
|
12
12
|
|
|
13
13
|
## Examples
|
|
14
14
|
|
|
@@ -19,8 +19,12 @@ It is therefore redundant to `extend` from `any`.
|
|
|
19
19
|
```ts
|
|
20
20
|
interface FooAny<T extends any> {}
|
|
21
21
|
|
|
22
|
+
interface FooUnknown<T extends unknown> {}
|
|
23
|
+
|
|
22
24
|
type BarAny<T extends any> = {};
|
|
23
25
|
|
|
26
|
+
type BarUnknown<T extends unknown> = {};
|
|
27
|
+
|
|
24
28
|
class BazAny<T extends any> {
|
|
25
29
|
quxAny<U extends any>() {}
|
|
26
30
|
}
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
---
|
|
2
|
+
description: 'Disallow comparing an enum value with a non-enum value.'
|
|
3
|
+
---
|
|
4
|
+
|
|
5
|
+
> 🛑 This file is source code, not the primary documentation location! 🛑
|
|
6
|
+
>
|
|
7
|
+
> See **https://typescript-eslint.io/rules/no-unsafe-enum-comparison** for documentation.
|
|
8
|
+
|
|
9
|
+
The TypeScript compiler can be surprisingly lenient when working with enums.
|
|
10
|
+
For example, it will allow you to compare enum values against numbers even though they might not have any type overlap:
|
|
11
|
+
|
|
12
|
+
```ts
|
|
13
|
+
enum Fruit {
|
|
14
|
+
Apple,
|
|
15
|
+
Banana,
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
declare let fruit: Fruit;
|
|
19
|
+
|
|
20
|
+
fruit === 999; // No error
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
This rule flags when an enum typed value is compared to a non-enum `number`.
|
|
24
|
+
|
|
25
|
+
## Examples
|
|
26
|
+
|
|
27
|
+
<!--tabs-->
|
|
28
|
+
|
|
29
|
+
### ❌ Incorrect
|
|
30
|
+
|
|
31
|
+
```ts
|
|
32
|
+
enum Fruit {
|
|
33
|
+
Apple,
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
declare let fruit: Fruit;
|
|
37
|
+
|
|
38
|
+
fruit === 999;
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
```ts
|
|
42
|
+
enum Vegetable {
|
|
43
|
+
Asparagus = 'asparagus',
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
declare let vegetable: Vegetable;
|
|
47
|
+
|
|
48
|
+
vegetable === 'asparagus';
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
### ✅ Correct
|
|
52
|
+
|
|
53
|
+
```ts
|
|
54
|
+
enum Fruit {
|
|
55
|
+
Apple,
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
declare let fruit: Fruit;
|
|
59
|
+
|
|
60
|
+
fruit === Fruit.Banana;
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
```ts
|
|
64
|
+
enum Vegetable {
|
|
65
|
+
Asparagus = 'asparagus',
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
declare let vegetable: Vegetable;
|
|
69
|
+
|
|
70
|
+
vegetable === Vegetable.Asparagus;
|
|
71
|
+
```
|
|
72
|
+
|
|
73
|
+
<!--/tabs-->
|
|
74
|
+
|
|
75
|
+
## When Not To Use It
|
|
76
|
+
|
|
77
|
+
If you don't mind number and/or literal string constants being compared against enums, you likely don't need this rule.
|
|
@@ -142,6 +142,29 @@ a ?? (b && c && d);
|
|
|
142
142
|
|
|
143
143
|
**_NOTE:_** Errors for this specific case will be presented as suggestions (see below), instead of fixes. This is because it is not always safe to automatically convert `||` to `??` within a mixed logical expression, as we cannot tell the intended precedence of the operator. Note that by design, `??` requires parentheses when used with `&&` or `||` in the same expression.
|
|
144
144
|
|
|
145
|
+
### `ignorePrimitives`
|
|
146
|
+
|
|
147
|
+
If you would like to ignore certain primitive types that can be falsy then you may pass an object containing a boolean value for each primitive:
|
|
148
|
+
|
|
149
|
+
- `string: true`, ignores `null` or `undefined` unions with `string` (default: false).
|
|
150
|
+
- `number: true`, ignores `null` or `undefined` unions with `number` (default: false).
|
|
151
|
+
- `bigint: true`, ignores `null` or `undefined` unions with `bigint` (default: false).
|
|
152
|
+
- `boolean: true`, ignores `null` or `undefined` unions with `boolean` (default: false).
|
|
153
|
+
|
|
154
|
+
Incorrect code for `ignorePrimitives: { string: true }`, and correct code for `ignorePrimitives: { string: false }`:
|
|
155
|
+
|
|
156
|
+
```ts
|
|
157
|
+
const foo: string | undefined = 'bar';
|
|
158
|
+
foo || 'a string';
|
|
159
|
+
```
|
|
160
|
+
|
|
161
|
+
Correct code for `ignorePrimitives: { string: true }`:
|
|
162
|
+
|
|
163
|
+
```ts
|
|
164
|
+
const foo: string | undefined = 'bar';
|
|
165
|
+
foo ?? 'a string';
|
|
166
|
+
```
|
|
167
|
+
|
|
145
168
|
## When Not To Use It
|
|
146
169
|
|
|
147
170
|
If you are not using TypeScript 3.7 (or greater), then you will not be able to use this rule, as the operator is not supported.
|
|
@@ -57,13 +57,204 @@ foo?.a?.b?.c?.d?.e;
|
|
|
57
57
|
|
|
58
58
|
<!--/tabs-->
|
|
59
59
|
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
60
|
+
## Options
|
|
61
|
+
|
|
62
|
+
In the context of the descriptions below a "loose boolean" operand is any operand that implicitly coerces the value to a boolean.
|
|
63
|
+
Specifically the argument of the not operator (`!loose`) or a bare value in a logical expression (`loose && looser`).
|
|
64
|
+
|
|
65
|
+
### `allowPotentiallyUnsafeFixesThatModifyTheReturnTypeIKnowWhatImDoing`
|
|
66
|
+
|
|
67
|
+
When this option is `true`, the rule will not provide an auto-fixer for cases where the return type of the expression would change. For example for the expression `!foo || foo.bar` the return type of the expression is `true | T`, however for the equivalent optional chain `foo?.bar` the return type of the expression is `undefined | T`. Thus changing the code from a logical expression to an optional chain expression has altered the type of the expression.
|
|
68
|
+
|
|
69
|
+
In some cases this distinction _may_ matter - which is why these fixers are considered unsafe - they may break the build! For example in the following code:
|
|
70
|
+
|
|
71
|
+
```ts
|
|
72
|
+
declare const foo: { bar: boolean } | null | undefined;
|
|
73
|
+
declare function acceptsBoolean(arg: boolean): void;
|
|
74
|
+
|
|
75
|
+
// ✅ typechecks succesfully as the expression only returns `boolean`
|
|
76
|
+
acceptsBoolean(foo != null && foo.bar);
|
|
77
|
+
|
|
78
|
+
// ❌ typechecks UNSUCCESSFULLY as the expression returns `boolean | undefined`
|
|
79
|
+
acceptsBoolean(foo != null && foo.bar);
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
This style of code isn't super common - which means having this option set to `true` _should_ be safe in most codebases. However we default it to `false` due to its unsafe nature. We have provided this option for convenience because it increases the autofix cases covered by the rule. If you set option to `true` the onus is entirely on you and your team to ensure that each fix is correct and safe and that it does not break the build.
|
|
83
|
+
|
|
84
|
+
When this option is `false` unsafe cases will have suggestion fixers provided instead of auto-fixers - meaning you can manually apply the fix using your IDE tooling.
|
|
85
|
+
|
|
86
|
+
### `checkAny`
|
|
87
|
+
|
|
88
|
+
When this option is `true` the rule will check operands that are typed as `any` when inspecting "loose boolean" operands.
|
|
89
|
+
|
|
90
|
+
<!--tabs-->
|
|
91
|
+
|
|
92
|
+
#### ❌ Incorrect for `checkAny: true`
|
|
93
|
+
|
|
94
|
+
```ts
|
|
95
|
+
declare const thing: any;
|
|
96
|
+
|
|
97
|
+
thing && thing.toString();
|
|
98
|
+
```
|
|
99
|
+
|
|
100
|
+
#### ✅ Correct for `checkAny: false`
|
|
101
|
+
|
|
102
|
+
```ts
|
|
103
|
+
declare const thing: any;
|
|
104
|
+
|
|
105
|
+
thing && thing.toString();
|
|
106
|
+
```
|
|
107
|
+
|
|
108
|
+
<!--/tabs-->
|
|
109
|
+
|
|
110
|
+
### `checkUnknown`
|
|
111
|
+
|
|
112
|
+
When this option is `true` the rule will check operands that are typed as `unknown` when inspecting "loose boolean" operands.
|
|
113
|
+
|
|
114
|
+
<!--tabs-->
|
|
115
|
+
|
|
116
|
+
#### ❌ Incorrect for `checkUnknown: true`
|
|
117
|
+
|
|
118
|
+
```ts
|
|
119
|
+
declare const thing: unknown;
|
|
120
|
+
|
|
121
|
+
thing && thing.toString();
|
|
122
|
+
```
|
|
123
|
+
|
|
124
|
+
#### ✅ Correct for `checkUnknown: false`
|
|
125
|
+
|
|
126
|
+
```ts
|
|
127
|
+
declare const thing: unknown;
|
|
128
|
+
|
|
129
|
+
thing && thing.toString();
|
|
130
|
+
```
|
|
131
|
+
|
|
132
|
+
<!--/tabs-->
|
|
133
|
+
|
|
134
|
+
### `checkString`
|
|
135
|
+
|
|
136
|
+
When this option is `true` the rule will check operands that are typed as `string` when inspecting "loose boolean" operands.
|
|
137
|
+
|
|
138
|
+
<!--tabs-->
|
|
139
|
+
|
|
140
|
+
#### ❌ Incorrect for `checkString: true`
|
|
141
|
+
|
|
142
|
+
```ts
|
|
143
|
+
declare const thing: string;
|
|
144
|
+
|
|
145
|
+
thing && thing.toString();
|
|
146
|
+
```
|
|
147
|
+
|
|
148
|
+
#### ✅ Correct for `checkString: false`
|
|
149
|
+
|
|
150
|
+
```ts
|
|
151
|
+
declare const thing: string;
|
|
152
|
+
|
|
153
|
+
thing && thing.toString();
|
|
154
|
+
```
|
|
155
|
+
|
|
156
|
+
<!--/tabs-->
|
|
157
|
+
|
|
158
|
+
### `checkNumber`
|
|
159
|
+
|
|
160
|
+
When this option is `true` the rule will check operands that are typed as `number` when inspecting "loose boolean" operands.
|
|
161
|
+
|
|
162
|
+
<!--tabs-->
|
|
163
|
+
|
|
164
|
+
#### ❌ Incorrect for `checkNumber: true`
|
|
165
|
+
|
|
166
|
+
```ts
|
|
167
|
+
declare const thing: number;
|
|
168
|
+
|
|
169
|
+
thing && thing.toString();
|
|
170
|
+
```
|
|
171
|
+
|
|
172
|
+
#### ✅ Correct for `checkNumber: false`
|
|
173
|
+
|
|
174
|
+
```ts
|
|
175
|
+
declare const thing: number;
|
|
176
|
+
|
|
177
|
+
thing && thing.toString();
|
|
178
|
+
```
|
|
179
|
+
|
|
180
|
+
<!--/tabs-->
|
|
181
|
+
|
|
182
|
+
### `checkBoolean`
|
|
183
|
+
|
|
184
|
+
When this option is `true` the rule will check operands that are typed as `boolean` when inspecting "loose boolean" operands.
|
|
185
|
+
|
|
186
|
+
<!--tabs-->
|
|
187
|
+
|
|
188
|
+
#### ❌ Incorrect for `checkBoolean: true`
|
|
189
|
+
|
|
190
|
+
```ts
|
|
191
|
+
declare const thing: boolean;
|
|
192
|
+
|
|
193
|
+
thing && thing.toString();
|
|
194
|
+
```
|
|
195
|
+
|
|
196
|
+
#### ✅ Correct for `checkBoolean: false`
|
|
197
|
+
|
|
198
|
+
```ts
|
|
199
|
+
declare const thing: boolean;
|
|
200
|
+
|
|
201
|
+
thing && thing.toString();
|
|
202
|
+
```
|
|
203
|
+
|
|
204
|
+
<!--/tabs-->
|
|
205
|
+
|
|
206
|
+
### `checkBigInt`
|
|
207
|
+
|
|
208
|
+
When this option is `true` the rule will check operands that are typed as `bigint` when inspecting "loose boolean" operands.
|
|
209
|
+
|
|
210
|
+
<!--tabs-->
|
|
211
|
+
|
|
212
|
+
#### ❌ Incorrect for `checkBigInt: true`
|
|
213
|
+
|
|
214
|
+
```ts
|
|
215
|
+
declare const thing: bigint;
|
|
216
|
+
|
|
217
|
+
thing && thing.toString();
|
|
218
|
+
```
|
|
219
|
+
|
|
220
|
+
#### ✅ Correct for `checkBigInt: false`
|
|
221
|
+
|
|
222
|
+
```ts
|
|
223
|
+
declare const thing: bigint;
|
|
224
|
+
|
|
225
|
+
thing && thing.toString();
|
|
226
|
+
```
|
|
227
|
+
|
|
228
|
+
<!--/tabs-->
|
|
229
|
+
|
|
230
|
+
### `requireNullish`
|
|
231
|
+
|
|
232
|
+
When this option is `true` the rule will skip operands that are not typed with `null` and/or `undefined` when inspecting "loose boolean" operands.
|
|
233
|
+
|
|
234
|
+
<!--tabs-->
|
|
235
|
+
|
|
236
|
+
#### ❌ Incorrect for `requireNullish: true`
|
|
237
|
+
|
|
238
|
+
```ts
|
|
239
|
+
declare const thing1: string | null;
|
|
240
|
+
thing1 && thing1.toString();
|
|
241
|
+
```
|
|
242
|
+
|
|
243
|
+
#### ✅ Correct for `requireNullish: true`
|
|
244
|
+
|
|
245
|
+
```ts
|
|
246
|
+
declare const thing1: string | null;
|
|
247
|
+
thing1?.toString();
|
|
248
|
+
|
|
249
|
+
declare const thing2: string;
|
|
250
|
+
thing2 && thing2.toString();
|
|
251
|
+
```
|
|
252
|
+
|
|
253
|
+
<!--/tabs-->
|
|
63
254
|
|
|
64
255
|
## When Not To Use It
|
|
65
256
|
|
|
66
|
-
If you don't mind using more explicit `&&`s, you don't need this rule.
|
|
257
|
+
If you don't mind using more explicit `&&`s/`||`s, you don't need this rule.
|
|
67
258
|
|
|
68
259
|
## Further Reading
|
|
69
260
|
|
|
@@ -18,70 +18,180 @@ This rule reports when a `+` operation combines two values of different types, o
|
|
|
18
18
|
### ❌ Incorrect
|
|
19
19
|
|
|
20
20
|
```ts
|
|
21
|
-
|
|
22
|
-
|
|
21
|
+
let foo = '5.5' + 5;
|
|
22
|
+
let foo = 1n + 1;
|
|
23
23
|
```
|
|
24
24
|
|
|
25
25
|
### ✅ Correct
|
|
26
26
|
|
|
27
27
|
```ts
|
|
28
|
-
|
|
29
|
-
|
|
28
|
+
let foo = parseInt('5.5', 10) + 10;
|
|
29
|
+
let foo = 1n + 1n;
|
|
30
30
|
```
|
|
31
31
|
|
|
32
32
|
## Options
|
|
33
33
|
|
|
34
|
-
|
|
34
|
+
:::caution
|
|
35
|
+
We generally recommend against using these options, as they limit which varieties of incorrect `+` usage can be checked.
|
|
36
|
+
This in turn severely limits the validation that the rule can do to ensure that resulting strings and numbers are correct.
|
|
37
|
+
|
|
38
|
+
Safer alternatives to using the `allow*` options include:
|
|
39
|
+
|
|
40
|
+
- Using variadic forms of logging APIs to avoid needing to `+` values.
|
|
41
|
+
```ts
|
|
42
|
+
// Remove this line
|
|
43
|
+
console.log('The result is ' + true);
|
|
44
|
+
// Add this line
|
|
45
|
+
console.log('The result is', true);
|
|
46
|
+
```
|
|
47
|
+
- Using `.toFixed()` to coerce numbers to well-formed string representations:
|
|
48
|
+
```ts
|
|
49
|
+
const number = 1.123456789;
|
|
50
|
+
const result = 'The number is ' + number.toFixed(2);
|
|
51
|
+
// result === 'The number is 1.12'
|
|
52
|
+
```
|
|
53
|
+
- Calling `.toString()` on other types to mark explicit and intentional string coercion:
|
|
54
|
+
```ts
|
|
55
|
+
const arg = '11';
|
|
56
|
+
const regex = /[0-9]/;
|
|
57
|
+
const result =
|
|
58
|
+
'The result of ' +
|
|
59
|
+
regex.toString() +
|
|
60
|
+
'.test("' +
|
|
61
|
+
arg +
|
|
62
|
+
'") is ' +
|
|
63
|
+
regex.test(arg).toString();
|
|
64
|
+
// result === 'The result of /[0-9]/.test("11") is true'
|
|
65
|
+
```
|
|
66
|
+
|
|
67
|
+
:::
|
|
35
68
|
|
|
36
|
-
|
|
69
|
+
### `allowAny`
|
|
70
|
+
|
|
71
|
+
Examples of code for this rule with `{ allowAny: true }`:
|
|
37
72
|
|
|
38
73
|
<!--tabs-->
|
|
39
74
|
|
|
40
75
|
#### ❌ Incorrect
|
|
41
76
|
|
|
42
77
|
```ts
|
|
43
|
-
|
|
78
|
+
let fn = (a: number, b: []) => a + b;
|
|
79
|
+
let fn = (a: string, b: []) => a + b;
|
|
80
|
+
```
|
|
44
81
|
|
|
45
|
-
|
|
46
|
-
foo += 'some data';
|
|
82
|
+
#### ✅ Correct
|
|
47
83
|
|
|
48
|
-
|
|
49
|
-
|
|
84
|
+
```ts
|
|
85
|
+
let fn = (a: number, b: any) => a + b;
|
|
86
|
+
let fn = (a: string, b: any) => a + b;
|
|
87
|
+
```
|
|
88
|
+
|
|
89
|
+
### `allowBoolean`
|
|
90
|
+
|
|
91
|
+
Examples of code for this rule with `{ allowBoolean: true }`:
|
|
92
|
+
|
|
93
|
+
<!--tabs-->
|
|
94
|
+
|
|
95
|
+
#### ❌ Incorrect
|
|
96
|
+
|
|
97
|
+
```ts
|
|
98
|
+
let fn = (a: number, b: unknown) => a + b;
|
|
99
|
+
let fn = (a: string, b: unknown) => a + b;
|
|
50
100
|
```
|
|
51
101
|
|
|
52
102
|
#### ✅ Correct
|
|
53
103
|
|
|
54
104
|
```ts
|
|
55
|
-
|
|
105
|
+
let fn = (a: number, b: boolean) => a + b;
|
|
106
|
+
let fn = (a: string, b: boolean) => a + b;
|
|
107
|
+
```
|
|
56
108
|
|
|
57
|
-
|
|
58
|
-
foo += 1;
|
|
109
|
+
### `allowNullish`
|
|
59
110
|
|
|
60
|
-
|
|
61
|
-
|
|
111
|
+
Examples of code for this rule with `{ allowNullish: true }`:
|
|
112
|
+
|
|
113
|
+
<!--tabs-->
|
|
114
|
+
|
|
115
|
+
#### ❌ Incorrect
|
|
116
|
+
|
|
117
|
+
```ts
|
|
118
|
+
let fn = (a: number, b: unknown) => a + b;
|
|
119
|
+
let fn = (a: number, b: never) => a + b;
|
|
120
|
+
let fn = (a: string, b: unknown) => a + b;
|
|
121
|
+
let fn = (a: string, b: never) => a + b;
|
|
62
122
|
```
|
|
63
123
|
|
|
64
|
-
|
|
124
|
+
#### ✅ Correct
|
|
65
125
|
|
|
66
|
-
|
|
126
|
+
```ts
|
|
127
|
+
let fn = (a: number, b: undefined) => a + b;
|
|
128
|
+
let fn = (a: number, b: null) => a + b;
|
|
129
|
+
let fn = (a: string, b: undefined) => a + b;
|
|
130
|
+
let fn = (a: string, b: null) => a + b;
|
|
131
|
+
```
|
|
132
|
+
|
|
133
|
+
### `allowNumberAndString`
|
|
134
|
+
|
|
135
|
+
Examples of code for this rule with `{ allowNumberAndString: true }`:
|
|
67
136
|
|
|
68
137
|
<!--tabs-->
|
|
69
138
|
|
|
70
139
|
#### ❌ Incorrect
|
|
71
140
|
|
|
72
141
|
```ts
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
var fn = (a: any, b: {}) => a + b;
|
|
142
|
+
let fn = (a: number, b: unknown) => a + b;
|
|
143
|
+
let fn = (a: number, b: never) => a + b;
|
|
76
144
|
```
|
|
77
145
|
|
|
78
146
|
#### ✅ Correct
|
|
79
147
|
|
|
80
148
|
```ts
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
149
|
+
let fn = (a: number, b: string) => a + b;
|
|
150
|
+
let fn = (a: number, b: number | string) => a + b;
|
|
151
|
+
```
|
|
152
|
+
|
|
153
|
+
### `allowRegExp`
|
|
154
|
+
|
|
155
|
+
Examples of code for this rule with `{ allowRegExp: true }`:
|
|
156
|
+
|
|
157
|
+
<!--tabs-->
|
|
158
|
+
|
|
159
|
+
#### ❌ Incorrect
|
|
160
|
+
|
|
161
|
+
```ts
|
|
162
|
+
let fn = (a: number, b: RegExp) => a + b;
|
|
163
|
+
```
|
|
164
|
+
|
|
165
|
+
#### ✅ Correct
|
|
166
|
+
|
|
167
|
+
```ts
|
|
168
|
+
let fn = (a: string, b: RegExp) => a + b;
|
|
169
|
+
```
|
|
170
|
+
|
|
171
|
+
### `skipCompoundAssignments`
|
|
172
|
+
|
|
173
|
+
Examples of code for this rule with `{ skipCompoundAssignments: true }`:
|
|
174
|
+
|
|
175
|
+
<!--tabs-->
|
|
176
|
+
|
|
177
|
+
#### ❌ Incorrect
|
|
178
|
+
|
|
179
|
+
```ts
|
|
180
|
+
let foo: string | undefined;
|
|
181
|
+
foo += 'some data';
|
|
182
|
+
|
|
183
|
+
let bar: string = '';
|
|
184
|
+
bar += 0;
|
|
185
|
+
```
|
|
186
|
+
|
|
187
|
+
#### ✅ Correct
|
|
188
|
+
|
|
189
|
+
```ts
|
|
190
|
+
let foo: number = 0;
|
|
191
|
+
foo += 1;
|
|
192
|
+
|
|
193
|
+
let bar = '';
|
|
194
|
+
bar += 'test';
|
|
85
195
|
```
|
|
86
196
|
|
|
87
197
|
## When Not To Use It
|
|
@@ -6,9 +6,19 @@ description: 'Enforce template literal expressions to be of `string` type.'
|
|
|
6
6
|
>
|
|
7
7
|
> See **https://typescript-eslint.io/rules/restrict-template-expressions** for documentation.
|
|
8
8
|
|
|
9
|
-
JavaScript
|
|
10
|
-
The default
|
|
11
|
-
This rule reports on values used in a template literal string that aren't
|
|
9
|
+
JavaScript automatically [converts an object to a string](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String#string_coercion) in a string context, such as when concatenating it with a string using `+` or embedding it in a template literal using `${}`.
|
|
10
|
+
The default `toString()` method of objects returns `"[object Object]"`, which is often not what was intended.
|
|
11
|
+
This rule reports on values used in a template literal string that aren't strings, numbers, or BigInts, optionally allowing other data types that provide useful stringification results.
|
|
12
|
+
|
|
13
|
+
:::note
|
|
14
|
+
|
|
15
|
+
This rule intentionally does not allow objects with a custom `toString()` method to be used in template literals, because the stringification result may not be user-friendly.
|
|
16
|
+
|
|
17
|
+
For example, arrays have a custom [`toString()`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/toString) method, which only calls `join()` internally, which joins the array elements with commas. This means that (1) array elements are not necessarily stringified to useful results (2) the commas don't have spaces after them, making the result not user-friendly. The best way to format arrays is to use [`Intl.ListFormat`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Intl/ListFormat), which even supports adding the "and" conjunction where necessary.
|
|
18
|
+
You must explicitly call `object.toString()` if you want to use this object in a template literal.
|
|
19
|
+
The [`no-base-to-string`](./no-base-to-string.md) rule can be used to guard this case against producing `"[object Object]"` by accident.
|
|
20
|
+
|
|
21
|
+
:::
|
|
12
22
|
|
|
13
23
|
## Examples
|
|
14
24
|
|
|
@@ -47,6 +57,8 @@ const msg1 = `arg = ${arg}`;
|
|
|
47
57
|
const msg2 = `arg = ${arg || 'zero'}`;
|
|
48
58
|
```
|
|
49
59
|
|
|
60
|
+
This option controls both numbers and BigInts.
|
|
61
|
+
|
|
50
62
|
### `allowBoolean`
|
|
51
63
|
|
|
52
64
|
Examples of additional **correct** code for this rule with `{ allowBoolean: true }`:
|