Search code examples
typescripteslintbun

Migrating to eslint 9.0.0 issue


I have next issue while upgrading eslint to 9.0.0

⋊> ~/A/fusion on turborepo ⨯ bun lint                                                          22:21:58
$ eslint packages/*/src/**/*

Oops! Something went wrong! :(

ESLint: 9.0.0

ConfigError: Config (unnamed): Key "plugins": Cannot redefine plugin "@typescript-eslint".
    at rethrowConfigError (/Users/aleksandrkireev/Apps/fusion/node_modules/@humanwhocodes/config-array/api.js:225:8)
    at /Users/aleksandrkireev/Apps/fusion/node_modules/@humanwhocodes/config-array/api.js:1018:5
    at Array.reduce (<anonymous>)
    at FlatConfigArray.getConfig (/Users/aleksandrkireev/Apps/fusion/node_modules/@humanwhocodes/config-array/api.js:1014:39)
    at FlatConfigArray.isFileIgnored (/Users/aleksandrkireev/Apps/fusion/node_modules/@humanwhocodes/config-array/api.js:1046:15)
    at /Users/aleksandrkireev/Apps/fusion/node_modules/eslint/lib/eslint/eslint-helpers.js:514:38
    at Array.forEach (<anonymous>)
    at findFiles (/Users/aleksandrkireev/Apps/fusion/node_modules/eslint/lib/eslint/eslint-helpers.js:503:11)
    at async ESLint.lintFiles (/Users/aleksandrkireev/Apps/fusion/node_modules/eslint/lib/eslint/eslint.js:846:27)
    at async Object.execute (/Users/aleksandrkireev/Apps/fusion/node_modules/eslint/lib/cli.js:461:23)
⋊> ~/A/fusion on turborepo ⨯             

I don't use @humanwhocodes package, but it seems some other package uses it.

Deps:

  "dependencies": {
    "alor-api": "1.0.47",
    "axios": "1.6.8",
    "cache-manager": "5.5.1",
    "core-js": "3.36.1",
    "create-hmac": "1.1.7",
    "crypto-hash": "3.0.0",
    "date-fns": "^2.28.0",
    "eslint-plugin-react-hooks": "4.6.0",
    "moment": "2.30.1",
    "msgpack5": "6.0.2",
    "node-cron": "3.0.3",
    "node-fetch": "3.3.2",
    "node-yaml-config": "1.0.0",
    "react": "18.2.0",
    "react-dom": "18.2.0",
    "react-error-overlay": "6.0.11",
    "reflect-metadata": "0.2.2",
    "regenerator-runtime": "0.14.1",
    "request": "2.88.2",
    "swr": "2.2.5",
    "tslib": "2.6.2",
    "winston": "^3.8.2",
    "winston-daily-rotate-file": "^4.7.1",
    "winston-loki": "^6.0.6",
    "winston-telegram": "^2.6.0"
  },
  "devDependencies": {
    "@testing-library/react": "14.3.0",
    "@types/bun": "^1.0.12",
    "@types/jest": "29.5.12",
    "@types/node": "20.12.5",
    "@types/node-fetch": "^2.6.11",
    "@types/react": "18.2.74",
    "@types/react-dom": "18.2.24",
    "@typescript-eslint/parser": "^7.5.0",
    "babel-jest": "29.7.0",
    "create-ts-index": "^1.14.0",
    "cypress": "13.7.2",
    "esbuild": "^0.20.2",
    "eslint": "^9.0.0",
    "eslint-config-next": "^14.1.4",
    "eslint-config-prettier": "^9.1.0",
    "eslint-config-standard-with-typescript": "^43.0.1",
    "eslint-plugin-cypress": "^2.10.3",
    "eslint-plugin-import": "^2.25.2",
    "eslint-plugin-jsx-a11y": "^6.8.0",
    "eslint-plugin-n": "^15.0.0 || ^16.0.0",
    "eslint-plugin-promise": "^6.0.0",
    "eslint-plugin-react": "^7.34.1",
    "eslint-plugin-unused-imports": "^3.1.0",
    "globals": "^15.0.0",
    "husky": "^9.0.11",
    "jest": "29.4.3",
    "jest-environment-jsdom": "29.4.3",
    "jest-environment-node": "^29.4.1",
    "lint-staged": "^13.1.0",
    "sass": "1.74.1",
    "ts-jest": "29.1.2",
    "ts-node": "^10.9.2",
    "tsconfig-paths": "^4.2.0",
    "typescript": "^5.4.4",
    "typescript-eslint": "^7.5.0",
    "url-loader": "^4.1.1"
  }

eslint.config.js:

import globals from "globals";
import tseslint from "typescript-eslint";
import pluginReactConfig from "eslint-plugin-react/configs/recommended.js";

import path from "path";
import { fileURLToPath } from "url";
import { FlatCompat } from "@eslint/eslintrc";
import pluginJs from "@eslint/js";

// mimic CommonJS variables -- not needed if using CommonJS
const __filename = fileURLToPath(import.meta.url);
const __dirname = path.dirname(__filename);
const compat = new FlatCompat({baseDirectory: __dirname, recommendedConfig: pluginJs.configs.recommended});

export default [
  {languageOptions: { globals: globals.browser }},
  ...compat.extends("standard-with-typescript"),
  ...tseslint.configs.recommendedTypeChecked,
  {
    languageOptions: {
      parserOptions: {
        project: true,
        tsconfigRootDir: import.meta.dirname,
      },
    },
  },
  pluginReactConfig,
];

Solution

  • I think the issue might be that you include @typescript-eslint two times by using the spread operator with both compat.extends("standard-with-typescript") and tseslint.configs.recommendedTypeChecked.


    If you check recommendedTypeChecked here: https://github.com/typescript-eslint/typescript-eslint/blob/main/packages/eslint-plugin/src/configs/recommended-type-checked.ts

    you can see it extends the base config: https://github.com/typescript-eslint/typescript-eslint/blob/main/packages/eslint-plugin/src/configs/base.ts

    It includes the @typescript-eslint plugin.


    I'm not sure what is happening with that FlatCompat thing you have going on there, but probably it results in including the same @typescript-eslint plugin again, leading to the error you get.