Skip to content

Commit db650a0

Browse files
feat: support TypeScript syntax in no-invalid-this rule (#19532)
1 parent dd20cf2 commit db650a0

File tree

4 files changed

+1025
-0
lines changed

4 files changed

+1025
-0
lines changed

docs/src/rules/no-invalid-this.md

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -284,6 +284,59 @@ obj.Foo = function Foo() {
284284

285285
:::
286286

287+
This rule additionally supports TypeScript type syntax.
288+
289+
Examples of **incorrect** TypeScript code for this rule:
290+
291+
:::incorrect
292+
293+
```ts
294+
/*eslint no-invalid-this: "error"*/
295+
296+
function foo(bar: string) {
297+
this.prop;
298+
console.log(bar)
299+
}
300+
301+
/** @this Obj */
302+
foo(function() {
303+
console.log(this);
304+
z(x => console.log(x, this));
305+
});
306+
307+
function foo() {
308+
class C {
309+
accessor [this.a] = foo;
310+
}
311+
}
312+
```
313+
314+
:::
315+
316+
Examples of **correct** TypeScript code for this rule:
317+
318+
:::correct
319+
320+
```ts
321+
/*eslint no-invalid-this: "error"*/
322+
323+
interface SomeType {
324+
prop: string;
325+
}
326+
327+
function foo(this: SomeType) {
328+
this.prop;
329+
}
330+
331+
class A {
332+
a = 5;
333+
b = this.a;
334+
accessor c = this.a;
335+
}
336+
```
337+
338+
:::
339+
287340
## When Not To Use It
288341

289342
If you don't want to be notified about usage of `this` keyword outside of classes or class-like objects, you can safely disable this rule.

lib/rules/no-invalid-this.js

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,8 @@ function isCodePathWithLexicalThis(codePath, node) {
3636
/** @type {import('../types').Rule.RuleModule} */
3737
module.exports = {
3838
meta: {
39+
dialects: ["javascript", "typescript"],
40+
language: "javascript",
3941
type: "suggestion",
4042

4143
defaultOptions: [{ capIsConstructor: true }],
@@ -140,8 +142,28 @@ module.exports = {
140142
stack.pop();
141143
},
142144

145+
"AccessorProperty > *.value"(node) {
146+
stack.push({
147+
init: true,
148+
node,
149+
valid: true,
150+
});
151+
},
152+
153+
"AccessorProperty:exit"() {
154+
stack.pop();
155+
},
156+
143157
// Reports if `this` of the current context is invalid.
144158
ThisExpression(node) {
159+
// Special case: skip `this` if it's the value of an AccessorProperty
160+
if (
161+
node.parent.type === "AccessorProperty" &&
162+
node.parent.value === node
163+
) {
164+
return;
165+
}
166+
145167
const current = stack.getCurrent();
146168

147169
if (current && !current.valid) {

lib/rules/utils/ast-utils.js

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1488,6 +1488,17 @@ module.exports = {
14881488
return false;
14891489
}
14901490

1491+
// Check if the function has a parameter named `this`.
1492+
if (
1493+
(node.type === "FunctionDeclaration" ||
1494+
node.type === "FunctionExpression") &&
1495+
node.params.some(
1496+
param => param.type === "Identifier" && param.name === "this",
1497+
)
1498+
) {
1499+
return false;
1500+
}
1501+
14911502
if (
14921503
(capIsConstructor && isES5Constructor(node)) ||
14931504
hasJSDocThisTag(node, sourceCode)

0 commit comments

Comments
 (0)