Skip to content

TSAbstractClassDeclaration are not defined in the scope (no-undef) #20

@JamesHenry

Description

@JamesHenry

This issue was initially reported here: eslint/typescript-eslint-parser#578


What version of TypeScript are you using?
3.1.3

What version of typescript-eslint-parser are you using?
21.0.2

What code were you trying to parse?

export abstract class Foo {}
export class FooBar extends Foo {}

What did you expect to happen?
No lint errors

What happened?

2:29 error 'Foo' is not defined no-undef

While I understand that Typescript already has scope checks that seem to make no-undef unnecessary and can be disabled, it has been useful to ensure that name and length are not accidentally used, see: microsoft/TypeScript#18433

Potential Fix 1

eslint-scope/lib/referencer.js:Referencer.visitClass adds a definition into the scope for "ClassDeclaration", which does not happen for "TSAbstractClassDeclaration". I think this can be fixed by doing:

TSAbstractClassDeclaration(node) {
    this.currentScope().__define(
        node.id,
        new Definition("ClassName", node.id, node, null, null, null)
    );
    this.ClassDeclaration(node);
}

However this then causes:

1:23 error 'Foo' is already declared in the upper scope no-shadow

Because of this special casing of ClassDeclaration in eslint/lib/rules/no-shadow.js:

/**
 * Checks if a variable of the class name in the class scope of ClassDeclaration.
 *
 * ClassDeclaration creates two variables of its name into its outer scope and its class scope.
 * So we should ignore the variable in the class scope.
 *
 * @param {Object} variable The variable to check.
 * @returns {boolean} Whether or not the variable of the class name in the class scope of ClassDeclaration.
 */
function isDuplicatedClassNameVariable(variable) {
    const block = variable.scope.block;

    return block.type === "ClassDeclaration" && block.id === variable.identifiers[0];
}

From here, I suppose you could just say that no-shadow should be disabled on typescript files, in favor of using tslint's no-shadowed-variables

Potential Fix 2

In typescript-eslint-parser/parser.js, we can simply re-map the abstract class node:

case "TSAbstractClassDeclaration":
    node.type = 'ClassDeclaration';
    break;

which to me seems pretty clean, since as far as eslint is concerned, the abstract keyword doesn't affect anything.

Metadata

Metadata

Assignees

Labels

bugSomething isn't workingpackage: eslint-pluginIssues related to @typescript-eslint/eslint-plugin

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions

    pFad - Phonifier reborn

    Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

    Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


    Alternative Proxies:

    Alternative Proxy

    pFad Proxy

    pFad v3 Proxy

    pFad v4 Proxy