Skip to content

Commit 93cbfc0

Browse files
authored
Add no-undeclared-class-members rule (#3153)
1 parent 5733173 commit 93cbfc0

7 files changed

Lines changed: 1171 additions & 0 deletions
Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
1+
# no-undeclared-class-members
2+
3+
📝 Require class members to be declared.
4+
5+
💼🚫 This rule is enabled in the ✅ `recommended` [config](https://github.com/sindresorhus/eslint-plugin-unicorn#recommended-config). This rule is _disabled_ in the ☑️ `unopinionated` [config](https://github.com/sindresorhus/eslint-plugin-unicorn#recommended-config).
6+
7+
💡 This rule is manually fixable by [editor suggestions](https://eslint.org/docs/latest/use/core-concepts#rule-suggestions).
8+
9+
<!-- end auto-generated rule header -->
10+
<!-- Do not manually modify this header. Run: `npm run fix:eslint-docs` -->
11+
12+
Class members should be declared when they are used through `this`. Declaring fields, methods, getters, and setters in the class body makes typos visible and gives readers the class shape upfront.
13+
14+
Constructor assignments like `this.name = name` are treated as declarations. Classes with `extends` are ignored because the accessed member may come from a superclass. Static `this`, private members, computed member access, and dynamic initialization patterns like `Object.assign(this, data)` are unsupported.
15+
16+
Editor suggestions are offered for simple non-constructor assignments like `this.name = name` when a declaration can be inserted cleanly. Reads, calls, compound assignments, updates, and constructor assignments are reported without a suggestion.
17+
18+
## Examples
19+
20+
```js
21+
//
22+
class Foo {
23+
getName() {
24+
return this.name;
25+
}
26+
}
27+
28+
//
29+
class Foo {
30+
name;
31+
32+
getName() {
33+
return this.name;
34+
}
35+
}
36+
```
37+
38+
```js
39+
//
40+
class Foo {
41+
callName() {
42+
this.name();
43+
}
44+
}
45+
46+
//
47+
class Foo {
48+
name() {}
49+
50+
callName() {
51+
this.name();
52+
}
53+
}
54+
```
55+
56+
```js
57+
//
58+
class Foo {
59+
constructor(name) {
60+
this.name = name;
61+
}
62+
63+
getName() {
64+
return this.name;
65+
}
66+
}
67+
```
68+
69+
> [!NOTE]
70+
> Declaring a class field like `name;` creates an own property with the value `undefined` on every instance before any method runs. This can change observable behavior, for example `Object.hasOwn(instance, 'name')`, so this rule provides editor suggestions instead of an autofix.

readme.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -145,6 +145,7 @@ export default [
145145
| [no-this-assignment](docs/rules/no-this-assignment.md) | Disallow assigning `this` to a variable. | ✅ ☑️ | | |
146146
| [no-this-outside-of-class](docs/rules/no-this-outside-of-class.md) | Disallow `this` outside of classes. || | |
147147
| [no-typeof-undefined](docs/rules/no-typeof-undefined.md) | Disallow comparing `undefined` using `typeof`. | ✅ ☑️ | 🔧 | 💡 |
148+
| [no-undeclared-class-members](docs/rules/no-undeclared-class-members.md) | Require class members to be declared. || | 💡 |
148149
| [no-unnecessary-array-flat-depth](docs/rules/no-unnecessary-array-flat-depth.md) | Disallow using `1` as the `depth` argument of `Array#flat()`. | ✅ ☑️ | 🔧 | |
149150
| [no-unnecessary-array-splice-count](docs/rules/no-unnecessary-array-splice-count.md) | Disallow using `.length` or `Infinity` as the `deleteCount` or `skipCount` argument of `Array#{splice,toSpliced}()`. | ✅ ☑️ | 🔧 | |
150151
| [no-unnecessary-await](docs/rules/no-unnecessary-await.md) | Disallow awaiting non-promise values. | ✅ ☑️ | 🔧 | |

rules/index.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -84,6 +84,7 @@ export {default as 'no-thenable'} from './no-thenable.js';
8484
export {default as 'no-this-assignment'} from './no-this-assignment.js';
8585
export {default as 'no-this-outside-of-class'} from './no-this-outside-of-class.js';
8686
export {default as 'no-typeof-undefined'} from './no-typeof-undefined.js';
87+
export {default as 'no-undeclared-class-members'} from './no-undeclared-class-members.js';
8788
export {default as 'no-unnecessary-array-flat-depth'} from './no-unnecessary-array-flat-depth.js';
8889
export {default as 'no-unnecessary-array-splice-count'} from './no-unnecessary-array-splice-count.js';
8990
export {default as 'no-unnecessary-await'} from './no-unnecessary-await.js';

0 commit comments

Comments
 (0)