diff --git a/packages/ast-spec/src/unions/EntityName.ts b/packages/ast-spec/src/unions/EntityName.ts index 82f7b1c9b0c..8a7364bef6b 100644 --- a/packages/ast-spec/src/unions/EntityName.ts +++ b/packages/ast-spec/src/unions/EntityName.ts @@ -1,4 +1,5 @@ import type { Identifier } from '../expression/Identifier/spec'; +import type { ThisExpression } from '../expression/ThisExpression/spec'; import type { TSQualifiedName } from '../type/TSQualifiedName/spec'; -export type EntityName = Identifier | TSQualifiedName; +export type EntityName = Identifier | ThisExpression | TSQualifiedName; diff --git a/packages/eslint-plugin/tests/eslint-rules/no-undef.test.ts b/packages/eslint-plugin/tests/eslint-rules/no-undef.test.ts index 53dd3be8d0d..3335e04e741 100644 --- a/packages/eslint-plugin/tests/eslint-rules/no-undef.test.ts +++ b/packages/eslint-plugin/tests/eslint-rules/no-undef.test.ts @@ -249,11 +249,12 @@ class Foo {} export type AppState = typeof import('./src/store/reducers').default; `, ` +let self: typeof this; +let foo: typeof this.foo; const obj = { foo: '', bar() { let self: typeof this; - let foo: typeof this.foo; }, }; `, diff --git a/packages/scope-manager/src/referencer/ClassVisitor.ts b/packages/scope-manager/src/referencer/ClassVisitor.ts index 6f505044213..306f064dc8a 100644 --- a/packages/scope-manager/src/referencer/ClassVisitor.ts +++ b/packages/scope-manager/src/referencer/ClassVisitor.ts @@ -293,7 +293,7 @@ class ClassVisitor extends Visitor { node.typeAnnotation.type === AST_NODE_TYPES.TSTypeReference && this.#emitDecoratorMetadata ) { - let identifier: TSESTree.Identifier; + let identifier: TSESTree.Identifier | TSESTree.ThisExpression; if ( node.typeAnnotation.typeName.type === AST_NODE_TYPES.TSQualifiedName ) { @@ -306,6 +306,10 @@ class ClassVisitor extends Visitor { identifier = node.typeAnnotation.typeName; } + if (identifier.type === AST_NODE_TYPES.ThisExpression) { + return; + } + if (withDecorators) { this.#referencer.currentScope().referenceDualValueType(identifier); diff --git a/packages/scope-manager/src/referencer/TypeVisitor.ts b/packages/scope-manager/src/referencer/TypeVisitor.ts index bbfbab23020..672058dfae0 100644 --- a/packages/scope-manager/src/referencer/TypeVisitor.ts +++ b/packages/scope-manager/src/referencer/TypeVisitor.ts @@ -256,24 +256,22 @@ class TypeVisitor extends Visitor { // a type query `typeof foo` is a special case that references a _non-type_ variable, protected TSTypeQuery(node: TSESTree.TSTypeQuery): void { - if (node.exprName.type === AST_NODE_TYPES.Identifier) { - this.#referencer.currentScope().referenceValue(node.exprName); - } else if ( - (node.exprName.type as unknown) === AST_NODE_TYPES.ThisExpression - ) { - // technically exprName is either Identifier or QualifiedName, but eslint does not recognize `typeof this`, - // so we have translated it to ThisExpression. - return; - } else { - let expr = node.exprName.left; - while (expr.type === TSESTree.AST_NODE_TYPES.TSQualifiedName) { - expr = expr.left; + let identifier: TSESTree.Identifier | TSESTree.ThisExpression; + if (node.exprName.type === AST_NODE_TYPES.TSQualifiedName) { + let iter = node.exprName; + while (iter.left.type === AST_NODE_TYPES.TSQualifiedName) { + iter = iter.left; } - if ((expr.type as unknown) === AST_NODE_TYPES.ThisExpression) { - return; - } - this.#referencer.currentScope().referenceValue(expr); + identifier = iter.left; + } else { + identifier = node.exprName; } + + if (identifier.type === AST_NODE_TYPES.ThisExpression) { + return; + } + + this.#referencer.currentScope().referenceValue(identifier); } protected TSTypeAnnotation(node: TSESTree.TSTypeAnnotation): void {