@@ -5,7 +5,7 @@ which provides a TypeScript ESLint ruleset tailored for large teams and projects
55Please see [ that project's documentation] ( https://www.npmjs.com/package/@rushstack/eslint-config )
66for details. To learn about Rush Stack, please visit: [ https://rushstack.io/ ] ( https://rushstack.io/ )
77
8- ### ` @rushstack/no-null `
8+ ## ` @rushstack/no-null `
99
1010Prevent usage of JavaScript's ` null ` keyword.
1111
@@ -49,44 +49,48 @@ if (x === null) { // comparisons are okay
4949}
5050```
5151
52- ### ` @rushstack/no-untyped-underscore ` (Opt-in)
52+ ## ` @rushstack/no-untyped-underscore ` (Opt-in)
5353
5454Prevent TypeScript code from accessing legacy JavaScript members whose name has an underscore prefix.
5555
5656#### Rule Details
5757
5858JavaScript does not provide a straightforward way to restrict access to object members, so API names commonly
59- use an underscore prefix to indicate a private member (e.g. ` exampleObject._privateMember ` ). However, inexperienced
60- developers may not be aware of this convention. In TypeScript we can generally solve this problem by marking the types
61- as ` private ` or omitting them from the typings. However, when migrating a large legacy code base to TypeScript,
62- it may be difficult to author typings for every legacy API. For this case, you can enable the
63- ` @rushstack/no-untyped-underscore ` rule.
59+ indicate a private member by using an underscore prefix (e.g. ` exampleObject._privateMember ` ). For inexperienced
60+ developers who may be unfamiliar with this convention, in TypeScript we can mark the APIs as ` private ` or omit them
61+ from the typings. However, when migrating a large code base to TypeScript, it may be difficult to declare types
62+ for every legacy API. In this situation, the ` @rushstack/no-untyped-underscore ` rule can help.
6463
65- This rule reports access to members whose name has an underscore prefix, EXCEPT in cases where:
64+ This rule detects expressions that access a member with an underscore prefix, EXCEPT in cases where:
6665
67- - The containing object has a type which declares the member; OR
68- - The untyped expression uses privileged names like ` this._example ` or ` that._example ` or ` super._example ` ; OR
66+ - The object is typed: specifically, ` exampleObject ` has a TypeScript type that declares ` _privateMember ` ; OR
67+ - The object expression uses: the ` this ` or ` super ` keywords; OR
68+ - The object expression is a variable named ` that ` . (In older ES5 code, ` that ` was commonly used as an alias
69+ for ` this ` in unbound contexts.)
6970
7071#### Examples
7172
7273The following patterns are considered problems when ` @rushstack/no-untyped-underscore ` is enabled:
7374
7475``` ts
7576let x: any ;
76- x ._privateMember = 123 ; // error
77+ x ._privateMember = 123 ; // error, because x is untyped
7778
7879let x: { [key : string ]: number };
79- x ._privateMember = 123 ; // error
80+ x ._privateMember = 123 ; // error, because _privateMember is not a declared member of x's type
8081```
8182
8283The following patterns are NOT considered problems:
8384
8485``` ts
8586let x: { _privateMember: any };
86- x ._privateMember = 123 ; // okay because _privateMember is declared by x's type
87+ x ._privateMember = 123 ; // okay, because _privateMember is declared by x's type
88+
89+ let x = { _privateMember: 0 };
90+ x ._privateMember = 123 ; // okay, because _privateMember is part of the inferred type
8791
8892enum E {
8993 _PrivateMember
9094}
91- let e: E ._PrivateMember = E ._PrivateMember ; // okay because _PrivateMember is declared by E
95+ let e: E ._PrivateMember = E ._PrivateMember ; // okay, because _PrivateMember is declared by E
9296```
0 commit comments