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): [parameter-properties] add rule to replace no-parameter-properties #4622

Merged
Merged
2 changes: 1 addition & 1 deletion packages/eslint-plugin/README.md
Expand Up @@ -135,7 +135,6 @@ Pro Tip: For larger codebases you may want to consider splitting our linting int
| [`@typescript-eslint/no-non-null-asserted-nullish-coalescing`](./docs/rules/no-non-null-asserted-nullish-coalescing.md) | Disallows using a non-null assertion in the left operand of the nullish coalescing operator | | | |
| [`@typescript-eslint/no-non-null-asserted-optional-chain`](./docs/rules/no-non-null-asserted-optional-chain.md) | Disallows using a non-null assertion after an optional chain expression | :white_check_mark: | | |
| [`@typescript-eslint/no-non-null-assertion`](./docs/rules/no-non-null-assertion.md) | Disallows non-null assertions using the `!` postfix operator | :white_check_mark: | | |
| [`@typescript-eslint/no-parameter-properties`](./docs/rules/no-parameter-properties.md) | Disallow the use of parameter properties in class constructors | | | |
| [`@typescript-eslint/no-redundant-type-constituents`](./docs/rules/no-redundant-type-constituents.md) | Disallow members of unions and intersections that do nothing or override type information | | | :thought_balloon: |
| [`@typescript-eslint/no-require-imports`](./docs/rules/no-require-imports.md) | Disallows invocation of `require()` | | | |
| [`@typescript-eslint/no-this-alias`](./docs/rules/no-this-alias.md) | Disallow aliasing `this` | :white_check_mark: | | |
Expand All @@ -154,6 +153,7 @@ Pro Tip: For larger codebases you may want to consider splitting our linting int
| [`@typescript-eslint/no-useless-empty-export`](./docs/rules/no-useless-empty-export.md) | Disallow empty exports that don't change anything in a module file | | :wrench: | |
| [`@typescript-eslint/no-var-requires`](./docs/rules/no-var-requires.md) | Disallows the use of require statements except in import statements | :white_check_mark: | | |
| [`@typescript-eslint/non-nullable-type-assertion-style`](./docs/rules/non-nullable-type-assertion-style.md) | Prefers a non-null assertion over explicit type cast when possible | | :wrench: | :thought_balloon: |
| [`@typescript-eslint/parameter-properties`](./docs/rules/parameter-properties.md) | Require or disallow the use of parameter properties in class constructors | | | |
| [`@typescript-eslint/prefer-as-const`](./docs/rules/prefer-as-const.md) | Prefer usage of `as const` over literal type | :white_check_mark: | :wrench: | |
| [`@typescript-eslint/prefer-enum-initializers`](./docs/rules/prefer-enum-initializers.md) | Prefer initializing each enums member value | | | |
| [`@typescript-eslint/prefer-for-of`](./docs/rules/prefer-for-of.md) | Prefer a ‘for-of’ loop over a standard ‘for’ loop if the index is only used to access the array being iterated | | | |
Expand Down
4 changes: 2 additions & 2 deletions packages/eslint-plugin/ROADMAP.md
Expand Up @@ -169,7 +169,7 @@ It lists all TSLint rules along side rules from the ESLint ecosystem that are th
| [`no-boolean-literal-compare`] || [`@typescript-eslint/no-unnecessary-boolean-literal-compare`] |
| [`no-consecutive-blank-lines`] | 🌟 | [`no-multiple-empty-lines`][no-multiple-empty-lines] |
| [`no-irregular-whitespace`] | 🌟 | [`no-irregular-whitespace`][no-irregular-whitespace] with `skipStrings: false` |
| [`no-parameter-properties`] || [`@typescript-eslint/no-parameter-properties`] |
| [`no-parameter-properties`] || [`@typescript-eslint/parameter-properties`] |
| [`no-redundant-jsdoc`] | 🔌 | [`jsdoc/no-types`] |
| [`no-reference-import`] || [`@typescript-eslint/triple-slash-reference`] |
| [`no-trailing-whitespace`] | 🌟 | [`no-trailing-spaces`][no-trailing-spaces] |
Expand Down Expand Up @@ -633,7 +633,7 @@ Relevant plugins: [`chai-expect-keywords`](https://github.com/gavinaiken/eslint-
[`@typescript-eslint/naming-convention`]: https://typescript-eslint.io/rules/naming-convention
[`@typescript-eslint/interface-name-prefix`]: https://typescript-eslint.io/rules/interface-name-prefix
[`@typescript-eslint/naming-convention`]: https://typescript-eslint.io/rules/naming-convention
[`@typescript-eslint/no-parameter-properties`]: https://typescript-eslint.io/rules/no-parameter-properties
[`@typescript-eslint/parameter-properties`]: https://typescript-eslint.io/rules/parameter-properties
[`@typescript-eslint/member-delimiter-style`]: https://typescript-eslint.io/rules/member-delimiter-style
[`@typescript-eslint/prefer-for-of`]: https://typescript-eslint.io/rules/prefer-for-of
[`@typescript-eslint/no-array-constructor`]: https://typescript-eslint.io/rules/no-array-constructor
Expand Down
2 changes: 1 addition & 1 deletion packages/eslint-plugin/docs/rules/README.md
Expand Up @@ -59,7 +59,7 @@ slug: /
| [`@typescript-eslint/no-non-null-asserted-nullish-coalescing`](./no-non-null-asserted-nullish-coalescing.md) | Disallows using a non-null assertion in the left operand of the nullish coalescing operator | | | |
| [`@typescript-eslint/no-non-null-asserted-optional-chain`](./no-non-null-asserted-optional-chain.md) | Disallows using a non-null assertion after an optional chain expression | :white_check_mark: | | |
| [`@typescript-eslint/no-non-null-assertion`](./no-non-null-assertion.md) | Disallows non-null assertions using the `!` postfix operator | :white_check_mark: | | |
| [`@typescript-eslint/no-parameter-properties`](./no-parameter-properties.md) | Disallow the use of parameter properties in class constructors | | | |
| [`@typescript-eslint/parameter-properties`](./parameter-properties.md) | Disallow the use of parameter properties in class constructors | | | |
| [`@typescript-eslint/no-require-imports`](./no-require-imports.md) | Disallows invocation of `require()` | | | |
| [`@typescript-eslint/no-this-alias`](./no-this-alias.md) | Disallow aliasing `this` | :white_check_mark: | | |
| [`@typescript-eslint/no-type-alias`](./no-type-alias.md) | Disallow the use of type aliases | | | |
Expand Down
@@ -1,6 +1,6 @@
# `no-parameter-properties`
# `parameter-properties`

Disallow the use of parameter properties in class constructors.
Require or disallow the use of parameter properties in class constructors.

Parameter properties can be confusing to those new to TypeScript as they are less explicit than other ways
of declaring and initializing class members.
Expand All @@ -13,7 +13,14 @@ declare all properties in the class.
## Options

This rule, in its default state, does not require any argument and would completely disallow the use of parameter properties.
If you would like to allow certain types of parameter properties then you may pass an object with the following options:
It may take an options object containing either or both of:

- `"allows"`: allowing certain kinds of properties to be ignored
- `"prefer"`: either `"class-properties"` _(default)_ or `"parameter-properties"`

### `"allows"`

If you would like to ignore certain kinds of properties then you may pass an object containing `"allows"` as an array of any of the following options:

- `allows`, an array containing one or more of the allowed modifiers. Valid values are:
- `readonly`, allows **readonly** parameter properties.
Expand All @@ -24,6 +31,29 @@ If you would like to allow certain types of parameter properties then you may pa
- `protected readonly`, allows **protected readonly** parameter properties.
- `public readonly`, allows **public readonly** parameter properties.

For example, to ignore `public` properties:

```json
{
"@typescript-eslint/parameter-properties": [
true,
{
"allow": ["public"]
}
]
}
```

### `"prefer"`

By default, the rule prefers class properties (`"class-properties"`).
You can switch it to instead preferring parameter properties with (`"parameter-properties"`).

In `"parameter-properties"` mode, the rule will issue a report when:

- A class property and constructor parameter have the same name and type
- The constructor parameter is assigned to the class property at the beginning of the constructor

### default

Examples of code for this rule with no options at all:
Expand Down Expand Up @@ -392,6 +422,63 @@ class Foo {
}
```

### `"parameter-properties"`

Examples of code for the `{ "prefer": ["parameter-properties"] }` option:

<!--tabs-->

#### ❌ Incorrect

```ts
class Foo {
private name: string;
constructor(name: string) {
this.name = name;
}
}

class Foo {
public readonly name: string;
constructor(name: string) {
this.name = name;
}
}

class Foo {
constructor(name: string) {
this.name = name;
}
name: string;
}
```

#### ✅ Correct

```ts
class Foo {
private differentName: string;
constructor(name: string) {
this.differentName = name;
}
}

class Foo {
private differentType: number | undefined;
constructor(differentType: number) {
this.differentType = differentType;
}
}

class Foo {
protected logicInConstructor: string;
constructor(logicInConstructor: string) {
console.log('Hello, world!');
this.logicInConstructor = logicInConstructor;
}
}
```

## When Not To Use It

If you don't care about the using parameter properties in constructors, then you will not need this rule.
Expand Down
2 changes: 1 addition & 1 deletion packages/eslint-plugin/src/configs/all.ts
Expand Up @@ -85,7 +85,7 @@ export = {
'@typescript-eslint/no-non-null-asserted-nullish-coalescing': 'error',
'@typescript-eslint/no-non-null-asserted-optional-chain': 'error',
'@typescript-eslint/no-non-null-assertion': 'error',
'@typescript-eslint/no-parameter-properties': 'error',
'@typescript-eslint/parameter-properties': 'error',
'no-redeclare': 'off',
'@typescript-eslint/no-redeclare': 'error',
'@typescript-eslint/no-redundant-type-constituents': 'error',
Expand Down
4 changes: 2 additions & 2 deletions packages/eslint-plugin/src/rules/index.ts
Expand Up @@ -58,7 +58,6 @@ import noNamespace from './no-namespace';
import noNonNullAssertedNullishCoalescing from './no-non-null-asserted-nullish-coalescing';
import noNonNullAssertedOptionalChain from './no-non-null-asserted-optional-chain';
import noNonNullAssertion from './no-non-null-assertion';
import noParameterProperties from './no-parameter-properties';
import noRedeclare from './no-redeclare';
import noRedundantTypeConstituents from './no-redundant-type-constituents';
import noRequireImports from './no-require-imports';
Expand Down Expand Up @@ -87,6 +86,7 @@ import noVarRequires from './no-var-requires';
import nonNullableTypeAssertionStyle from './non-nullable-type-assertion-style';
import objectCurlySpacing from './object-curly-spacing';
import paddingLineBetweenStatements from './padding-line-between-statements';
import parameterProperties from './parameter-properties';
import preferAsConst from './prefer-as-const';
import preferEnumInitializers from './prefer-enum-initializers';
import preferForOf from './prefer-for-of';
Expand Down Expand Up @@ -184,7 +184,6 @@ export default {
'no-non-null-asserted-nullish-coalescing': noNonNullAssertedNullishCoalescing,
'no-non-null-asserted-optional-chain': noNonNullAssertedOptionalChain,
'no-non-null-assertion': noNonNullAssertion,
'no-parameter-properties': noParameterProperties,
JoshuaKGoldberg marked this conversation as resolved.
Show resolved Hide resolved
'no-redeclare': noRedeclare,
'no-redundant-type-constituents': noRedundantTypeConstituents,
'no-require-imports': noRequireImports,
Expand Down Expand Up @@ -213,6 +212,7 @@ export default {
'non-nullable-type-assertion-style': nonNullableTypeAssertionStyle,
'object-curly-spacing': objectCurlySpacing,
'padding-line-between-statements': paddingLineBetweenStatements,
'parameter-properties': parameterProperties,
'prefer-as-const': preferAsConst,
'prefer-enum-initializers': preferEnumInitializers,
'prefer-for-of': preferForOf,
Expand Down
110 changes: 0 additions & 110 deletions packages/eslint-plugin/src/rules/no-parameter-properties.ts

This file was deleted.