Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix: make plugin assignable to ESLint.Plugin (again) #423

Merged
merged 1 commit into from
Jun 17, 2024

Conversation

JstnMcBrd
Copy link
Contributor

@JstnMcBrd JstnMcBrd commented Jun 16, 2024

Linked Issues


Long description


Here's the issue: the types for ESLint mandate that plugin configs must be a Record<string, ConfigData | Linter.FlatConfig | Linter.FlatConfig[]>. This means that all members must be config objects.

However, the stylistic plugin tries to include a function in the configs - the customize() method. By doing so, giving the plugin to ESLint makes TypeScript explode.



The easiest solution? Just remove customize() from the configs object and include it as a separate export of the package. This would make the stylistic plugin normal and perfectly fit the types.

However, this would be a breaking change and require a major version bump to 3.0.0. And it would be undoing the original intent of the project maintainers. So I tried to find a less disruptive solution.



Previously, in #418, I tried to define the plugin's configs object as being an extension of ESLint.Plugin['configs'].

declare const plugin: {
  ...,
  configs: ESLint.Plugin['configs'] & typeof configs
}

Turns out, TypeScript is smarter than that and sees right through our little trick. It uses the configs object type still.



It appears the only way to solve the issue is to define the configs object itself as an extension of ESLint.Plugin['configs']. It's possible by just doing this:

export const configs = {
   ...,
} as ESLint.Plugin['configs']

But this causes a new problem: it generifies the type for the object, so TypeScript can no longer provide suggestions for indexing the config object. In an IDE, the user can no longer see what the names of the available configs are.



So I tried to find a solution that defined the configs object as being an extension of ESLint.Plugin['configs'] plus its own specific type.

Turns out, the only way to do that was to define a private _configs object, then export it as a new configs object with ESLint.Plugin['configs'] and typeof _configs.

const _configs = {
   ...,
}
export const configs = _configs as ESLint.Plugin['configs'] & typeof _configs

In the auto-generated dts file, this changes the configs object type:

- declare const configs: {
+ declare const configs: Record<string, ESLint.ConfigData | Linter.FlatConfig | Linter.FlatConfig[]> & {
   ...
}

Finally! Exactly what we've been looking for!

And this time, I copied the generated dts file into my personal project's node_modules/@stylistic/eslint-plugin/dist folder to verify that it actually solves the problem.

Now, is this elegant? No, it's a little messy. But I couldn't find a better way that

  • made the plugin compatible with ESLint's plugin type
  • didn't remove the customize() function from the configs object
  • preserved the explicit type of the configs object with all config names


Hopefully writing out my thought process helps make this weird change make more sense. Please let me know if you have any suggestions.


Closes #398 (again)

Copy link

codecov bot commented Jun 16, 2024

Codecov Report

All modified and coverable lines are covered by tests ✅

Project coverage is 99.79%. Comparing base (7f3efde) to head (c874e11).

Additional details and impacted files
@@           Coverage Diff           @@
##             main     #423   +/-   ##
=======================================
  Coverage   99.79%   99.79%           
=======================================
  Files         118      118           
  Lines       27748    27748           
  Branches     4716     4716           
=======================================
  Hits        27691    27691           
  Misses         57       57           

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

@antfu antfu added this pull request to the merge queue Jun 17, 2024
Merged via the queue into eslint-stylistic:main with commit 9fc0cc5 Jun 17, 2024
11 checks passed
@JstnMcBrd JstnMcBrd deleted the JstnMcBrd/fix-398 branch June 17, 2024 17:39
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Types: '@stylistic/eslint-plugin' is not assignable to 'ESLint.Plugin'
2 participants