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" } }
问题根源
- 全局启用了
@typescript-eslint/consistent-type-imports规则,但全局parserOptions未配置project,且.ts/.tsx文件未指定@typescript-eslint/parser,导致规则无法获取必要的parser服务。 - 使用
FlatCompat转换旧版配置时,overrides中的vue配置优先级不足,且相对路径的project可能存在解析问题。 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
相关产品推荐
相关产品推荐

