eslint icon indicating copy to clipboard operation
eslint copied to clipboard

Bug: 9.39 breaks plugin type

Open jendrikw opened this issue 2 months ago • 12 comments

Environment

Node version: v20.19.1 npm version: v10.8.2 Local ESLint version: v9.39.1 (Currently used) Global ESLint version: Not found Operating System: linux 5.0 (X11)

What parser are you using?

Default (Espree)

What did you do?

Configuration

import html from '@html-eslint/eslint-plugin';
import { defineConfig } from 'eslint/config';

export default defineConfig({
  files: ['src/**/*.html'],
  plugins: { html },
  language: 'html/html',
  extends: ['html/recommended'],
});

When using typescript with exactOptionalPropertyTypes, It spits out an error since eslint v9.39:

eslint.config.mjs:14:19 - error TS2322: Type 'typeof import("/REPO/node_modules/@html-eslint/eslint-plugin/types/index")' is not assignable to type 'Plugin'.
  Types of property 'rules' are incompatible.
    Type 'Record<string, import("/REPO/node_modules/@eslint/core/dist/cjs/types").RuleDefinition<import("/REPO/node_modules/@eslint/core/dist/cjs/types").RuleDefinitionTypeOptions>>' is not assignable to type 'Record<string, import("/REPO/node_modules/eslint/node_modules/@eslint/core/dist/cjs/types").RuleDefinition<import("/REPO/node_modules/eslint/node_modules/@eslint/core/dist/cjs/types").RuleDefinitionTypeOptions>>'.
      'string' index signatures are incompatible.
        Type 'import("/REPO/node_modules/@eslint/core/dist/cjs/types").RuleDefinition<import("/REPO/node_modules/@eslint/core/dist/cjs/types").RuleDefinitionTypeOptions>' is not assignable to type 'import("/REPO/node_modules/eslint/node_modules/@eslint/core/dist/cjs/types").RuleDefinition<import("/REPO/node_modules/eslint/node_modules/@eslint/core/dist/cjs/types").RuleDefinitionTypeOptions>' with 'exactOptionalPropertyTypes: true'. Consider adding 'undefined' to the types of the target's properties.
          Types of property 'create' are incompatible.
            Type '(context: import("/REPO/node_modules/@eslint/core/dist/cjs/types").RuleContext<{ LangOptions: import("/REPO/node_modules/@eslint/core/dist/cjs/types").LanguageOptions; Code: import("/REPO/node_modules/@eslint/core/dist/cjs/types").SourceCode<...' is not assignable to type '(context: import("/REPO/node_modules/eslint/node_modules/@eslint/core/dist/cjs/types").RuleContext<{ LangOptions: import("/REPO/node_modules/eslint/node_modules/@eslint/core/dist/cjs/types").LanguageOptions; Code: import("/REPO/node_modules/e...'.
              Types of parameters 'context' and 'context' are incompatible.
                Type 'import("/REPO/node_modules/eslint/node_modules/@eslint/core/dist/cjs/types").RuleContext<{ LangOptions: import("/REPO/node_modules/eslint/node_modules/@eslint/core/dist/cjs/types").LanguageOptions; Code: import("/REPO/node_modules/eslint/node...' is not assignable to type 'import("/REPO/node_modules/@eslint/core/dist/cjs/types").RuleContext<{ LangOptions: import("/REPO/node_modules/@eslint/core/dist/cjs/types").LanguageOptions; Code: import("/REPO/node_modules/@eslint/core/dist/cjs/types").SourceCode<{ LangOpti...'.
                  Types of property 'report' are incompatible.
                    Type '(violation: import("/REPO/node_modules/eslint/node_modules/@eslint/core/dist/cjs/types").ViolationReport<unknown, string>) => void' is not assignable to type '(violation: import("/REPO/node_modules/@eslint/core/dist/cjs/types").ViolationReport<unknown, string>) => void'.
                      Types of parameters 'violation' and 'violation' are incompatible.
                        Type 'import("/REPO/node_modules/@eslint/core/dist/cjs/types").ViolationReport<unknown, string>' is not assignable to type 'import("/REPO/node_modules/eslint/node_modules/@eslint/core/dist/cjs/types").ViolationReport<unknown, string>'.
                          Type 'ViolationReportBase & { message: string; } & { loc: SourceLocation | Position; }' is not assignable to type 'ViolationReport<unknown, string>'.
                            Type 'ViolationReportBase & { message: string; } & { loc: import("/REPO/node_modules/@eslint/core/dist/cjs/types").SourceLocation | import("/REPO/node_modules/@eslint/core/dist/cjs/types").Position; }' is not assignable to type 'import("/REPO/node_modules/eslint/node_modules/@eslint/core/dist/cjs/types").ViolationReportBase & { message: string; } & { loc: import("/REPO/node_modules/eslint/node_modules/@eslint/core/dist/cjs/types").SourceLocation | import("/REPO/node_...'.
                              Type 'ViolationReportBase & { message: string; } & { loc: SourceLocation | Position; }' is not assignable to type 'ViolationReportBase'.
                                Types of property 'suggest' are incompatible.
                                  Type 'import("/REPO/node_modules/@eslint/core/dist/cjs/types").SuggestedEdit[] | null | undefined' is not assignable to type 'import("/REPO/node_modules/eslint/node_modules/@eslint/core/dist/cjs/types").SuggestedEdit[] | null | undefined'.
                                    Type 'import("/REPO/node_modules/@eslint/core/dist/cjs/types").SuggestedEdit[]' is not assignable to type 'import("/REPO/node_modules/eslint/node_modules/@eslint/core/dist/cjs/types").SuggestedEdit[]'.
                                      Type 'import("/REPO/node_modules/@eslint/core/dist/cjs/types").SuggestedEdit' is not assignable to type 'import("/REPO/node_modules/eslint/node_modules/@eslint/core/dist/cjs/types").SuggestedEdit'.
                                        Type 'SuggestedEditBase & { desc: string; }' is not assignable to type 'SuggestedEdit'.
                                          Type 'SuggestedEditBase & { desc: string; }' is not assignable to type 'import("/REPO/node_modules/eslint/node_modules/@eslint/core/dist/cjs/types").SuggestedEditBase & { desc: string; }'.
                                            Type 'SuggestedEditBase & { desc: string; }' is not assignable to type 'SuggestedEditBase'.
                                              Types of property 'fix' are incompatible.
                                                Type 'RuleFixer | null | undefined' is not assignable to type 'RuleFixer'.
                                                  Type 'undefined' is not assignable to type 'RuleFixer'.

14         plugins: {html},
                     ~~~~


Found 1 error in eslint.config.mjs:14

What did you expect to happen?

No breaking changes on a minor release.

What actually happened?

My build broke. Maybe it would be possible for eslint to add some test that typecheck using common plugins so breaking changes can be detected before release?

Link to Minimal Reproducible Example

https://stackblitz.com/edit/stackblitz-starters-eyzcmbhz?file=eslint.config.mjs Run tsc -p .

Participation

  • [ ] I am willing to submit a pull request for this issue.

Additional comments

It seems to affect other plugins too:

  • https://github.com/eslint/json/issues/178
  • https://github.com/eslint/markdown/issues/577

See also https://github.com/eslint/eslint/issues/20286

The root cause seems to be in @eslint/core between 0.16 and 0.17.

jendrikw avatar Nov 04 '25 13:11 jendrikw

Confirmed, thanks for the report. I believe this problem will have to be fixed in one of @eslint/plugin-kit or @html-eslint/eslint-plugin by updating/broadening a dependency range.

Maybe it would be possible for eslint to add some test that typecheck using common plugins so breaking changes can be detected before release?

We do have type integration tests for some common plugins such as eslint-webpack-plugin or neostandard. Maybe @html-eslint/eslint-plugin should be included, too? @eslint/eslint-team

fasttime avatar Nov 06 '25 07:11 fasttime

I'm +1 on adding @html-eslint/eslint-plugin to the type tests.

Per the blog post and since Code Explorer already includes @html-eslint/eslint-plugin, I think this is a desirable way to add HTML support to ESLint.

lumirlumir avatar Nov 06 '25 07:11 lumirlumir

👍, and I suggest adding @eslint/json, @eslint/markdown, @eslint/css, too. (it can be caught by them as @lumirlumir mentioned somewhere).

aladdin-add avatar Nov 06 '25 07:11 aladdin-add

fwiw our type-checking is breaking on v9.39 due to @types/eslint-scope which we have to require for vue-eslint-parser.

A min reproduction should be:

// eslint.config.js
const parserVueESLintParser = require('vue-eslint-parser');

/** @type {import('eslint').Linter.FlatConfig[]} */
const config = [{languageOptions: { parser: parserVueESLintParser }}];

module.exports = config;
npm i eslint @types/eslint-scope typescript vue-eslint-parser

npx tsc --noEmit --target esnext --module esnext --moduleResolution bundler --allowJs eslint.config.js
which will give you all of these errors
node_modules/@types/eslint-scope/index.d.cts(87,5): error TS2416: Property 'globalScope' in type 'ScopeManager' is not assignable to the same property in base type 'ScopeManager'.
  Type 'GlobalScope' is not assignable to type 'Scope'.
    Types of property 'upper' are incompatible.
      Type 'Scope<Variable<Reference>, Reference> | null' is not assignable to type 'Scope | null'.
        Type 'Scope<Variable<Reference>, Reference>' is not assignable to type 'Scope'.
          Types of property 'implicit' are incompatible.
            Property 'variables' is missing in type '{ left: Reference[]; set: Map<string, Variable<Reference>>; }' but required in type '{ variables: Variable[]; set: Map<string, Variable>; }'.
node_modules/@types/eslint-scope/index.d.cts(92,5): error TS2416: Property 'scopes' in type 'ScopeManager' is not assignable to the same property in base type 'ScopeManager'.
  Type 'Scope<Variable<Reference>, Reference>[]' is not assignable to type 'Scope[]'.
    Type 'Scope<Variable<Reference>, Reference>' is not assignable to type 'Scope'.
      Types of property 'implicit' are incompatible.
        Property 'variables' is missing in type '{ left: Reference[]; set: Map<string, Variable<Reference>>; }' but required in type '{ variables: Variable[]; set: Map<string, Variable>; }'.
node_modules/@types/eslint-scope/index.d.cts(100,5): error TS2416: Property 'acquire' in type 'ScopeManager' is not assignable to the same property in base type 'ScopeManager'.
  Type '(node: Node, inner?: boolean | undefined) => Scope<Variable<Reference>, Reference> | null' is not assignable to type '(node: Node, inner?: boolean | undefined) => Scope | null'.
    Type 'Scope<Variable<Reference>, Reference> | null' is not assignable to type 'Scope | null'.
      Type 'Scope<Variable<Reference>, Reference>' is not assignable to type 'Scope'.
        Types of property 'implicit' are incompatible.
          Property 'variables' is missing in type '{ left: Reference[]; set: Map<string, Variable<Reference>>; }' but required in type '{ variables: Variable[]; set: Map<string, Variable>; }'.
node_modules/@types/eslint-scope/index.d.cts(123,5): error TS2416: Property 'getDeclaredVariables' in type 'ScopeManager' is not assignable to the same property in base type 'ScopeManager'.
  Type '(node: Node) => Variable<Reference>[]' is not assignable to type '(node: Node) => Variable[]'.
    Type 'Variable<Reference>[]' is not assignable to type 'Variable[]'.
      Type 'Variable<Reference>' is not assignable to type 'Variable'.
        The types of 'scope.implicit' are incompatible between these types.
          Property 'variables' is missing in type '{ left: Reference[]; set: Map<string, Variable<Reference>>; }' but required in type '{ variables: Variable[]; set: Map<string, Variable>; }'.
node_modules/@types/eslint-scope/index.d.cts(169,5): error TS2416: Property 'upper' in type 'Scope<TVariable, TReference>' is not assignable to the same property in base type 'Scope'.
  Type 'Scope<Variable<Reference>, Reference> | null' is not assignable to type 'Scope | null'.
    Type 'Scope<Variable<Reference>, Reference>' is not assignable to type 'Scope'.
      Types of property 'implicit' are incompatible.
        Property 'variables' is missing in type '{ left: Reference[]; set: Map<string, Variable<Reference>>; }' but required in type '{ variables: Variable[]; set: Map<string, Variable>; }'.
node_modules/@types/eslint-scope/index.d.cts(174,5): error TS2416: Property 'variableScope' in type 'Scope<TVariable, TReference>' is not assignable to the same property in base type 'Scope'.
  Type 'this' is not assignable to type 'Scope'.
    Type 'Scope<TVariable, TReference>' is not assignable to type 'Scope'.
      Types of property 'upper' are incompatible.
        Type 'Scope<Variable<Reference>, Reference> | null' is not assignable to type 'Scope | null'.
          Type 'Scope<Variable<Reference>, Reference>' is not assignable to type 'Scope'.
            Types of property 'implicit' are incompatible.
              Property 'variables' is missing in type '{ left: Reference[]; set: Map<string, Variable<Reference>>; }' but required in type '{ variables: Variable[]; set: Map<string, Variable>; }'.
node_modules/@types/eslint-scope/index.d.cts(179,5): error TS2416: Property 'variables' in type 'Scope<TVariable, TReference>' is not assignable to the same property in base type 'Scope'.
  Type 'TVariable[]' is not assignable to type 'Variable[]'.
    Type 'TVariable' is not assignable to type 'Variable'.
      Type 'Variable<Reference>' is not assignable to type 'Variable'.
        The types of 'scope.implicit' are incompatible between these types.
          Property 'variables' is missing in type '{ left: Reference[]; set: Map<string, Variable<Reference>>; }' but required in type '{ variables: Variable[]; set: Map<string, Variable>; }'.
node_modules/@types/eslint-scope/index.d.cts(184,5): error TS2416: Property 'references' in type 'Scope<TVariable, TReference>' is not assignable to the same property in base type 'Scope'.
  Type 'TReference[]' is not assignable to type 'Reference[]'.
    Type 'TReference' is not assignable to type 'Reference'.
      Type 'import("/home/jones/workspace/projects-scrap/eslint-typechecking/node_modules/@types/eslint-scope/index").Reference' is not assignable to type 'import("/home/jones/workspace/projects-scrap/eslint-typechecking/node_modules/eslint/lib/types/index").Scope.Reference'.
        The types of 'from.implicit' are incompatible between these types.
          Property 'variables' is missing in type '{ left: Reference[]; set: Map<string, Variable<Reference>>; }' but required in type '{ variables: Variable[]; set: Map<string, Variable>; }'.
node_modules/@types/eslint-scope/index.d.cts(189,5): error TS2416: Property 'childScopes' in type 'Scope<TVariable, TReference>' is not assignable to the same property in base type 'Scope'.
  Type 'Scope<Variable<Reference>, Reference>[]' is not assignable to type 'Scope[]'.
    Type 'Scope<Variable<Reference>, Reference>' is not assignable to type 'Scope'.
      Types of property 'implicit' are incompatible.
        Property 'variables' is missing in type '{ left: Reference[]; set: Map<string, Variable<Reference>>; }' but required in type '{ variables: Variable[]; set: Map<string, Variable>; }'.
node_modules/@types/eslint-scope/index.d.cts(204,5): error TS2416: Property 'implicit' in type 'Scope<TVariable, TReference>' is not assignable to the same property in base type 'Scope'.
  Property 'variables' is missing in type '{ left: TReference[]; set: Map<string, Variable<Reference>>; }' but required in type '{ variables: Variable[]; set: Map<string, Variable>; }'.
node_modules/@types/eslint-scope/index.d.cts(349,5): error TS2416: Property 'scope' in type 'Variable<TReference>' is not assignable to the same property in base type 'Variable'.
  Type 'Scope<Variable<Reference>, Reference>' is not assignable to type 'Scope'.
    Types of property 'implicit' are incompatible.
      Property 'variables' is missing in type '{ left: Reference[]; set: Map<string, Variable<Reference>>; }' but required in type '{ variables: Variable[]; set: Map<string, Variable>; }'.
node_modules/@types/eslint-scope/index.d.cts(359,5): error TS2416: Property 'references' in type 'Variable<TReference>' is not assignable to the same property in base type 'Variable'.
  Type 'TReference[]' is not assignable to type 'Reference[]'.
    Type 'TReference' is not assignable to type 'Reference'.
      Type 'import("/home/jones/workspace/projects-scrap/eslint-typechecking/node_modules/@types/eslint-scope/index").Reference' is not assignable to type 'import("/home/jones/workspace/projects-scrap/eslint-typechecking/node_modules/eslint/lib/types/index").Scope.Reference'.
        The types of 'from.implicit' are incompatible between these types.
          Property 'variables' is missing in type '{ left: Reference[]; set: Map<string, Variable<Reference>>; }' but required in type '{ variables: Variable[]; set: Map<string, Variable>; }'.
node_modules/@types/eslint-scope/index.d.cts(409,5): error TS2416: Property 'resolved' in type 'Reference' is not assignable to the same property in base type 'Reference'.
  Type 'Variable<Reference> | null' is not assignable to type 'Variable | null'.
    Type 'Variable<Reference>' is not assignable to type 'Variable'.
      The types of 'scope.implicit' are incompatible between these types.
        Property 'variables' is missing in type '{ left: Reference[]; set: Map<string, Variable<Reference>>; }' but required in type '{ variables: Variable[]; set: Map<string, Variable>; }'.
node_modules/@types/eslint-scope/index.d.cts(429,5): error TS2416: Property 'from' in type 'Reference' is not assignable to the same property in base type 'Reference'.
  Type 'Scope<Variable<Reference>, Reference>' is not assignable to type 'Scope'.
    Types of property 'implicit' are incompatible.
      Property 'variables' is missing in type '{ left: Reference[]; set: Map<string, Variable<Reference>>; }' but required in type '{ variables: Variable[]; set: Map<string, Variable>; }'.
node_modules/vue-eslint-parser/index.d.ts(64,35): error TS2307: Cannot find module '@typescript-eslint/utils' or its corresponding type declarations.

(the one about @typescript-eslint/utils not being found can be ignored, as it is unrelated and does not change the other errors)

G-Rath avatar Nov 16 '25 20:11 G-Rath

@G-Rath We don't maintain @types/eslint-scope. The next release of eslint-scope will ship with built-in types. You can discuss this problem and track progress in eslint/js#708.

fasttime avatar Nov 17 '25 13:11 fasttime

Maybe @html-eslint/eslint-plugin should be included, too?

I'm 👍 to this proposal. Marking as accepted.

nzakas avatar Nov 18 '25 16:11 nzakas

It looks like the types in the latest release of html-eslint (0.48.0) are still not compatible with ESLint v9.39.1 or ESLint v10.0.0-alpha.0. I'll reach out to the maintainer.

fasttime avatar Nov 18 '25 21:11 fasttime

This is the issue in html-eslint: yeonjuan/html-eslint#448.

fasttime avatar Nov 19 '25 12:11 fasttime

html-eslint v0.49.0 has types compatible with ESLint v9.39.1 and ESLint v10.0.0-alpha.0, so we can now proceed to extend the type integration tests.

fasttime avatar Nov 20 '25 20:11 fasttime

I’ll work on adding the type integration tests for @html-eslint/eslint-plugin.

sethamus avatar Nov 22 '25 13:11 sethamus

I’ll work on adding the type integration tests for @html-eslint/eslint-plugin.

Thanks @sethamus!

fasttime avatar Nov 22 '25 17:11 fasttime

👋 Hi! This issue is being addressed in pull request https://github.com/eslint/eslint/pull/20345. Thanks, @sethamus!

eslint-github-bot[bot] avatar Nov 23 '25 04:11 eslint-github-bot[bot]