Skip to content

Commit 05ebea5

Browse files
authored
feat(eslint-plugin): add no-unused-vars-experimental (#688)
1 parent ad7e1a7 commit 05ebea5

File tree

10 files changed

+1893
-3
lines changed

10 files changed

+1893
-3
lines changed

Diff for: packages/eslint-plugin/README.md

+1
Original file line numberDiff line numberDiff line change
@@ -186,6 +186,7 @@ Then you should add `airbnb` (or `airbnb-base`) to your `extends` section of `.e
186186
| [`@typescript-eslint/no-untyped-public-signature`](./docs/rules/no-untyped-public-signature.md) | Requires that all public method arguments and return type will be explicitly typed | | | |
187187
| [`@typescript-eslint/no-unused-expressions`](./docs/rules/no-unused-expressions.md) | Disallow unused expressions | | | |
188188
| [`@typescript-eslint/no-unused-vars`](./docs/rules/no-unused-vars.md) | Disallow unused variables | :heavy_check_mark: | | |
189+
| [`@typescript-eslint/no-unused-vars-experimental`](./docs/rules/no-unused-vars-experimental.md) | Disallow unused variables and arguments. | | | :thought_balloon: |
189190
| [`@typescript-eslint/no-use-before-define`](./docs/rules/no-use-before-define.md) | Disallow the use of variables before they are defined | :heavy_check_mark: | | |
190191
| [`@typescript-eslint/no-useless-constructor`](./docs/rules/no-useless-constructor.md) | Disallow unnecessary constructors | | | |
191192
| [`@typescript-eslint/no-var-requires`](./docs/rules/no-var-requires.md) | Disallows the use of require statements except in import statements | :heavy_check_mark: | | |
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,115 @@
1+
# Disallow unused variables and arguments (no-unused-vars-experimental)
2+
3+
Variables that are declared and not used anywhere in the code are most likely an error due to incomplete refactoring. Such variables take up space in the code and can lead to confusion by readers.
4+
5+
## Rule Details
6+
7+
This rule leverages the TypeScript compiler's unused variable checks to report. This means that with all rule options set to `false`, it should report the same errors as if you used both the `noUnusedLocals` and `noUnusedParameters` compiler options.
8+
9+
This rule is vastly different to, and maintains no compatability with the base eslint version of the rule.
10+
11+
### Limitations
12+
13+
There are two limitations to this rule when compared with eslint's `no-unused-vars` rule, which are imposed by the fact that it directly uses TypeScript's implementation.
14+
15+
1. This rule only works on files that TypeScript deems is a module (i.e. it has an `import` or an `export` statement).
16+
2. The rule is significantly less configurable, as it cannot deviate too far from the base implementation.
17+
18+
## Supported Nodes
19+
20+
This rule supports checks on the following features:
21+
22+
- Declarations:
23+
- `var` / `const` / `let`
24+
- `function`
25+
- `class`
26+
- `enum`
27+
- `interface`
28+
- `type`
29+
- Class methods
30+
- Class properties and parameter properties
31+
- Function parameters
32+
- Generic type parameters
33+
- Import statements
34+
35+
## Options
36+
37+
```ts
38+
type Options = {
39+
ignoredNamesRegex?: string | boolean;
40+
ignoreArgsIfArgsAfterAreUsed?: boolean;
41+
};
42+
43+
const defaultOptions: Options = {
44+
ignoredNamesRegex: '^_',
45+
ignoreArgsIfArgsAfterAreUsed: false,
46+
};
47+
```
48+
49+
### ignoredNamesRegex
50+
51+
This option accepts a regex string to match names against.
52+
Any matched names will be ignored and have no errors reported.
53+
If you set it to false, it will never ignore any names.
54+
55+
The default value is `'^_'` (i.e. matches any name prefixed with an underscore).
56+
57+
Examples of valid code with `{ variables: { ignoredNamesRegex: '^_' } }`.
58+
59+
```ts
60+
const _unusedVar = 'unused';
61+
class _Unused {
62+
private _unused = 1;
63+
private _unusedMethod() {}
64+
}
65+
function _unusedFunction() {}
66+
enum _UnusedEnum {
67+
a = 1,
68+
}
69+
interface _UnusedInterface {}
70+
type _UnusedType = {};
71+
```
72+
73+
**_NOTE:_** The TypeScript compiler automatically ignores imports, function arguments, type parameter declarations, and object destructuring variables prefixed with an underscore.
74+
As this is hard-coded into the compiler, we cannot change this.
75+
76+
Examples of valid code based on the unchangable compiler settings
77+
78+
```ts
79+
import _UnusedDefault, { _UnusedNamed } from 'foo';
80+
export function foo(_unusedProp: string) {}
81+
export class Foo<_UnusedGeneric> {}
82+
const { prop: _unusedDesctructure } = foo;
83+
```
84+
85+
## ignoreArgsIfArgsAfterAreUsed
86+
87+
When true, this option will ignore unused function arguments if the arguments proceeding arguments are used.
88+
89+
Examples of invalid code with `{ ignoreArgsIfArgsAfterAreUsed: false }`
90+
91+
```ts
92+
function foo(unused: string, used: number) {
93+
console.log(used);
94+
}
95+
96+
class Foo {
97+
constructor(unused: string, public used: number) {
98+
console.log(used);
99+
}
100+
}
101+
```
102+
103+
Examples of valid code with `{ ignoreArgsIfArgsAfterAreUsed: true }`
104+
105+
```ts
106+
function foo(unused: string, used: number) {
107+
console.log(used);
108+
}
109+
110+
class Foo {
111+
constructor(unused: string, public used: number) {
112+
console.log(used);
113+
}
114+
}
115+
```

Diff for: packages/eslint-plugin/src/configs/all.json

+2-1
Original file line numberDiff line numberDiff line change
@@ -31,8 +31,8 @@
3131
"@typescript-eslint/no-empty-function": "error",
3232
"@typescript-eslint/no-empty-interface": "error",
3333
"@typescript-eslint/no-explicit-any": "error",
34-
"no-extra-parens": "off",
3534
"@typescript-eslint/no-extra-non-null-assertion": "error",
35+
"no-extra-parens": "off",
3636
"@typescript-eslint/no-extra-parens": "error",
3737
"@typescript-eslint/no-extraneous-class": "error",
3838
"@typescript-eslint/no-floating-promises": "error",
@@ -57,6 +57,7 @@
5757
"@typescript-eslint/no-unused-expressions": "error",
5858
"no-unused-vars": "off",
5959
"@typescript-eslint/no-unused-vars": "error",
60+
"@typescript-eslint/no-unused-vars-experimental": "error",
6061
"no-use-before-define": "off",
6162
"@typescript-eslint/no-use-before-define": "error",
6263
"no-useless-constructor": "off",

Diff for: packages/eslint-plugin/src/rules/index.ts

+2
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,7 @@ import noUnnecessaryCondition from './no-unnecessary-condition';
4141
import noUnnecessaryQualifier from './no-unnecessary-qualifier';
4242
import noUnnecessaryTypeAssertion from './no-unnecessary-type-assertion';
4343
import noUnusedVars from './no-unused-vars';
44+
import noUnusedVarsExperimental from './no-unused-vars-experimental';
4445
import noUntypedPublicSignature from './no-untyped-public-signature';
4546
import noUnusedExpressions from './no-unused-expressions';
4647
import noUseBeforeDefine from './no-use-before-define';
@@ -116,6 +117,7 @@ export default {
116117
'no-unnecessary-type-assertion': noUnnecessaryTypeAssertion,
117118
'no-untyped-public-signature': noUntypedPublicSignature,
118119
'no-unused-vars': noUnusedVars,
120+
'no-unused-vars-experimental': noUnusedVarsExperimental,
119121
'no-unused-expressions': noUnusedExpressions,
120122
'no-use-before-define': noUseBeforeDefine,
121123
'no-useless-constructor': noUselessConstructor,

0 commit comments

Comments
 (0)