Skip to content

Change Request: Make rules TypeScript syntax-aware #19173

@JoshuaKGoldberg

Description

@JoshuaKGoldberg

ESLint version

9.15.0

What problem do you want to solve?

Forking out of #19134 & typescript-eslint/typescript-eslint#10338 -> #19169 (comment):

The only acceptable way to extend a core rule is to copy the file into your own project and then wrap it however you want. That does put more maintenance burden on plugin developers, but that's the point. If you want to do something that isn't officially supported, you need to take full responsibility for that implementation.

This is not an ideal situation for plugin developers. The required extra work in lieu of having a pluggable API or abstractions necessitates that plugin developers:

  • Maintain automations to keep up with ESLint's releases - including copying rules and any imported dependencies from ESLint core & its package dependencies
    • Amusingly, this again leads plugins to rely on implementation details. Just, now that would only be during their build steps, not their published packages
  • Be deeply familiar with and having a dependency on the potentially any/all implementation details of base rules

Much of that work is already in play today, including taking the dependency on base rules. Both the current unsupported approach and the recommended "copy and wrap" approach cause higher-than-expected levels of implementation detail reliance in extensions.

What do you think is the correct solution?

I honestly have no good idea. If the goal of ESLint is to not allow plugins to rely on any behavior from rules -which is my interpretation of eslint/rfcs#80 (comment) - then generalizing any of the following strategies we typically do in typescript-eslint seem moot.

For example, @typescript-eslint/no-unused-expressions effectively wraps the base rule's ExpressionStatement with filtering logic. But if we can't rely on the base rule having any particular node selectors, then... 🤷

If the ESLint team has appetite to work with plugin developers on this, maybe it would be useful as a next step for someone to gather all the various extension rules and strategies they've taken? Just to see what the landscape & common strategies are?

Participation

  • I am willing to submit a pull request for this change.

Additional comments

Personally, I don't think resolving this issue should block #19169. The "don't do this" urge with the current "copy and wrap" recommended approach can be added regardless of this issue. I suspect finding a more preferable strategy (this issue) will take much longer. If and when an alternate strategy is resolved, it can always add it to the docs.

I'll also note that plugins aren't "choosing" to write extension rules: they have to to satisfy user need. For example, typescript-eslint's extension rules must act the same as their base rules except for cases where TypeScript's syntax and/or type checking change something. I see extension rules as an expected use case for plugins that just hasn't yet had a formalized first-party ESLint API. If plugins could avoid taking any dependency on core rule behavior in this way -and therefore inconveniencing the ESLint project- that would be even better!


Edit (March 2025): The discussion is long enough that comments are being hidden by default. Turning the rules from #19173 (comment) into a task list here:

Metadata

Metadata

Assignees

Labels

acceptedThere is consensus among the team that this change meets the criteria for inclusioncoreRelates to ESLint's core APIs and featuresenhancementThis change enhances an existing feature of ESLint

Type

No type

Projects

Status

Implementing

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions