fix: make plugin assignable to ESLint.Plugin (again) #423
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Linked Issues
Types: '@stylistic/eslint-plugin' is not assignable to 'ESLint.Plugin' #398
Make plugin assignable to ESLint.Plugin #418 (previous PR that failed to solve the issue)
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 - thecustomize()
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 thestylistic
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']
.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: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 newconfigs
object withESLint.Plugin['configs']
andtypeof _configs
.In the auto-generated dts file, this changes the
configs
object type: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
customize()
function from the configs objectHopefully 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)