You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

ESLint迁移至v9.x:配置parserOptions.project遇报错求助

ESLint v8迁移至v9.1.0时@typescript-eslint/consistent-type-imports规则报错修复

问题描述

将ESLint从v8升级到v9.1.0后,运行lint命令时出现如下错误:

加载@typescript-eslint/consistent-type-imports规则时,需为@typescript-eslint/parser提供parserOptions.project属性以生成parserServices,且检测到非@typescript-eslint/parser的解析器,需确保其转发该配置。

已尝试为*.vue文件添加自定义配置但未生效,尝试的配置片段:

{
  files: ['*.vue'],
  parser: 'vue-eslint-parser',
  parserOptions: {
    parser: '@typescript-eslint/parser',
    project: './tsconfig.json',
    extraFileExtensions: ['.vue'],
    ecmaVersion: 'latest',
    ecmaFeatures: {
      jsx: true,
    },
  },
  rules: {
    'no-undef': 'off',
  },
},

配置文件参考

eslint.config.js

import { fileURLToPath } from 'url'
import path from 'path'
import { FlatCompat } from '@eslint/eslintrc'
import js from '@eslint/js'
import tseslint from 'typescript-eslint';
import markdown from 'eslint-plugin-markdown'
const __filename = fileURLToPath(import.meta.url)
const __dirname = path.dirname(__filename)

console.log(path.resolve('.', './tsconfig.json'))  
// /Users/xxxx-rd/repo/vue3-works/internal/eslintlib/tsconfig.json


const compat = new FlatCompat({
  baseDirectory: __dirname,
  resolvePluginsRelativeTo: __dirname,
  recommendedConfig: js.configs.recommended,
})

export default [
  ...markdown.configs.recommended,
  {
    ignores: ['dist', '**/*.d.ts'],
  },
  ...compat.config({
    env: {
      node: true,
      browser: true,
      es2022: true,
    },
    plugins: ['@typescript-eslint', 'eslint-plugin-tsdoc', 'unicorn'],
    extends: [
      'eslint:recommended',
      'plugin:import/recommended',
      'plugin:eslint-comments/recommended',
      'plugin:jsonc/recommended-with-jsonc',
      'plugin:vue/recommended',
      'plugin:@typescript-eslint/recommended',
    ],
    parserOptions: {
      ecmaVersion: 'latest',
    },
    settings: {
      'import/resolver': {
        node: {
          extensions: ['.js', 'mjs', '.jsx', '.ts', '.tsx', '.d.ts'],
        },
      },
    },
    overrides: [
      {
        files: ['*.json', '*.json5', '*.jsonc'],
        parser: 'jsonc-eslint-parser',
      },

      {
        files: ['*.vue'],
        parser: 'vue-eslint-parser',
        parserOptions: {
          parser: '@typescript-eslint/parser',
          project: './tsconfig.json',
          extraFileExtensions: ['.vue'],
          ecmaVersion: 'latest',
          ecmaFeatures: {
            jsx: true,
          },
        },
        rules: {
          'no-undef': 'off',
        },
      },
    ],
    rules: {
      '@typescript-eslint/explicit-module-boundary-types': 'off',
      '@typescript-eslint/no-explicit-any': 'off',
      '@typescript-eslint/no-non-null-assertion': 'off',
      '@typescript-eslint/no-non-null-asserted-optional-chain': 'off',
      '@typescript-eslint/consistent-type-imports': ['error', { disallowTypeAnnotations: false }],
      '@typescript-eslint/ban-ts-comment': ['off', { 'ts-ignore': false }],
      '@typescript-eslint/ban-types': [
        'error',
        {
          extendDefaults: true,
          types: {
            '{}': false,
          },
        },
      ],

      'import/default': 'off',
      'import/no-named-as-default': 'off',
      'import/no-named-as-default-member': 'off',
    },
  }),
]

tsconfig.json

{
  "compilerOptions": {
    "target": "ES2020",
    "useDefineForClassFields": true,
    "module": "ESNext",
    "lib": ["ES2020", "DOM", "DOM.Iterable"],
    "skipLibCheck": true,

    /* Bundler mode */
    "moduleResolution": "Bundler",
    "allowImportingTsExtensions": true,
    "resolveJsonModule": true,
    "isolatedModules": true,
    "noEmit": true,
    "allowJs": true,

    /* Linting */
    "strict": true,
    "noUnusedLocals": true,
    "noUnusedParameters": true,
    "noFallthroughCasesInSwitch": true
  },
  "include": ["src","**/*.config.ts", "**/*.config.js"]
}

package.json

{
  "name": "@eslint9",
  "private": false,
  "version": "0.0.2",
  "type": "module",
  "files": [
    "dist"
  ],
  "main": "./dist/umd/index.umd.js",
  "module": "./dist/es/index.mjs",
  "types": "./dist/types/index.d.ts",
  "exports": {
    "types": "./dist/types/index.d.ts",
    "import": "./dist/es/index.mjs",
    "require": "./dist/umd/index.umd.js"
  },
  "scripts": {
    "dev": "vite",
    "build": "tsc && vite build",
    "lint": "eslint ."
  },
  "devDependencies": {
    "@typescript-eslint/eslint-plugin": "^7.9.0",
    "@typescript-eslint/parser": "^7.9.0",
    "vue-tsc": "^2.0.6"
  },
  "peerDependencies": {
    "@eslint/js": "^9.1.1",
    "@types/node": "^20.12.7",
    "@typescript-eslint/eslint-plugin": "^7.9.0",
    "@typescript-eslint/parser": "^7.9.0",
    "eslint": "^9.1.0",
    "eslint-plugin-eslint-comments": "^3.2.0",
    "eslint-plugin-import": "^2.29.1",
    "eslint-plugin-jsonc": "^2.15.1",
    "eslint-plugin-markdown": "^5.0.0",
    "eslint-plugin-tsdoc": "^0.2.17",
    "eslint-plugin-unicorn": "^53.0.0",
    "eslint-plugin-vue": "^9.25.0",
    "typescript": "^5.4.5",
    "typescript-eslint": "^7.8.0",
    "vite": "^5.2.10",
    "vite-plugin-dts": "^3.9.0",
    "vite-plugin-eslint": "^1.8.1"
  }
}

问题根源

  1. 全局启用了@typescript-eslint/consistent-type-imports规则,但全局parserOptions未配置project,且.ts/.tsx文件未指定@typescript-eslint/parser,导致规则无法获取必要的parser服务。
  2. 使用FlatCompat转换旧版配置时,overrides中的vue配置优先级不足,且相对路径的project可能存在解析问题。
  3. tsconfig.json未包含.vue文件,导致TypeScript无法识别这些文件的类型信息。

修复方案

1. 重构ESLint配置,拆分文件类型规则

修改eslint.config.js,将TS/TSX、Vue文件的配置单独拆分,避免FlatCompat的兼容性问题:

import { fileURLToPath } from 'url'
import path from 'path'
import { FlatCompat } from '@eslint/eslintrc'
import js from '@eslint/js'
import tseslint from 'typescript-eslint';
import markdown from 'eslint-plugin-markdown'

const __filename = fileURLToPath(import.meta.url)
const __dirname = path.dirname(__filename)
// 使用绝对路径指定tsconfig,避免解析错误
const tsconfigPath = path.resolve(__dirname, './tsconfig.json')

const compat = new FlatCompat({
  baseDirectory: __dirname,
  resolvePluginsRelativeTo: __dirname,
  recommendedConfig: js.configs.recommended,
})

export default [
  ...markdown.configs.recommended,
  {
    ignores: ['dist', '**/*.d.ts'],
  },
  // 基础JS/全局配置
  ...compat.config({
    env: {
      node: true,
      browser: true,
      es2022: true,
    },
    plugins: ['eslint-plugin-tsdoc', 'unicorn'],
    extends: [
      'eslint:recommended',
      'plugin:import/recommended',
      'plugin:eslint-comments/recommended',
      'plugin:jsonc/recommended-with-jsonc',
    ],
    parserOptions: {
      ecmaVersion: 'latest',
    },
    settings: {
      'import/resolver': {
        node: {
          extensions: ['.js', 'mjs', '.jsx', '.ts', '.tsx', '.d.ts', '.vue'],
        },
      },
    },
    overrides: [
      {
        files: ['*.json', '*.json5', '*.jsonc'],
        parser: 'jsonc-eslint-parser',
      },
    ],
    rules: {
      'import/default': 'off',
      'import/no-named-as-default': 'off',
      'import/no-named-as-default-member': 'off',
    },
  }),
  // TS/TSX文件专属配置
  ...tseslint.config({
    files: ['*.ts', '*.tsx'],
    extends: ['plugin:@typescript-eslint/recommended'],
    parser: '@typescript-eslint/parser',
    parserOptions: {
      project: tsconfigPath,
      ecmaVersion: 'latest',
      ecmaFeatures: { jsx: true },
    },
    plugins: ['@typescript-eslint'],
    rules: {
      '@typescript-eslint/explicit-module-boundary-types': 'off',
      '@typescript-eslint/no-explicit-any': 'off',
      '@typescript-eslint/no-non-null-assertion': 'off',
      '@typescript-eslint/no-non-null-asserted-optional-chain': 'off',
      '@typescript-eslint/consistent-type-imports': ['error', { disallowTypeAnnotations: false }],
      '@typescript-eslint/ban-ts-comment': ['off', { 'ts-ignore': false }],
      '@typescript-eslint/ban-types': [
        'error',
        {
          extendDefaults: true,
          types: { '{}': false },
        },
      ],
    },
  }),
  // Vue文件专属配置
  {
    files: ['*.vue'],
    extends: ['plugin:vue/recommended'],
    parser: 'vue-eslint-parser',
    parserOptions: {
      parser: '@typescript-eslint/parser',
      project: tsconfigPath,
      extraFileExtensions: ['.vue'],
      ecmaVersion: 'latest',
      ecmaFeatures: { jsx: true },
    },
    plugins: ['vue', '@typescript-eslint'],
    rules: {
      'no-undef': 'off',
      '@typescript-eslint/consistent-type-imports': ['error', { disallowTypeAnnotations: false }],
    },
  },
]

2. 更新tsconfig.json,包含Vue文件

修改tsconfig.json的include数组,添加.vue文件:

{
  "compilerOptions": {
    // 原有配置不变
  },
  "include": ["src","**/*.config.ts", "**/*.config.js", "**/*.vue"]
}

3. 统一依赖版本

修改package.json中peerDependencies的typescript-eslint版本,与@typescript-eslint/*保持一致:

"peerDependencies": {
  // 其他依赖不变
  "typescript-eslint": "^7.9.0",
}

验证修复

运行npm run lint或yarn lint,确认错误消失,规则正常生效。

内容的提问来源于stack exchange,提问作者D.C

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.24 01:05:54