The plugin does not function properly when `languageOptions.projectService` is enabled
Checklist
- [x] I have tried restarting my IDE and the issue persists.
- [x] I have read the FAQ and my problem is not listed.
Tell us about your environment
- ESLint version: 9.16.0
- eslint-plugin-vue version: 9.32.0
- Vue version: 3.5.13
- Node version: 22.11.0
- Operating System: Windows11
Please show your full configuration:
// @ts-check
import eslint from "@eslint/js";
import tseslint from "typescript-eslint";
import pluginVue from "eslint-plugin-vue";
export default tseslint.config(
eslint.configs.recommended,
tseslint.configs.recommended,
...pluginVue.configs["flat/recommended"],
{
files: ["*.vue", "**/*.vue"],
languageOptions: {
parserOptions: {
parser: tseslint.parser,
ecmaFeatures: {
jsx: true,
},
extraFileExtensions: [".vue"],
projectService: true, // If you comment out this line, it will work.
tsconfigRootDir: import.meta.dirname,
},
},
}
);
What did you do?
When languageOptions.projectService is set to true, it reports errors for JSX but does not report errors for Vue.
<script setup lang="tsx">
const jsxComponent = <div>This is a jsx component</div>
</script>
<template>
<jsxComponent></jsxComponent>
<div></div>
</template>
What did you expect to happen?
The errors related to JSX should not be reported, and errors related to Vue should be reported.
/project/workspace/src/App.vue
6:3 warning Require self-closing on Vue.js custom components (<jsxComponent>) vue/html-self-closing
7:3 warning Require self-closing on HTML elements (<div>) vue/html-self-closing
✖ 2 problems (0 errors, 2 warnings)
0 errors and 2 warnings potentially fixable with the `--fix` option.
What actually happened?
/project/workspace/src/App.vue
2:31 error Parsing error: ',' expected
✖ 1 problem (1 error, 0 warnings)
Repository to reproduce this issue
https://codesandbox.io/p/devbox/cvwhrs
This has nothing to do with projectService. It's that you tell ESLint to parse Vue files with typescript-eslint's parser. Instead, you have to use eslint-parser-vue, which in turn you can tell to use typescript-eslint's parser for the JavaScript/TypeScript parts of Vue components. See e.g. https://eslint.vuejs.org/user-guide/#example-configuration-with-typescript-eslint-and-prettier.
This has nothing to do with
projectService. It's that you tell ESLint to parse Vue files with typescript-eslint's parser. Instead, you have to use eslint-parser-vue, which in turn you can tell to use typescript-eslint's parser for the JavaScript/TypeScript parts of Vue components. See e.g. eslint.vuejs.org/user-guide#example-configuration-with-typescript-eslint-and-prettier.
I need to enable Linting with Type Information for typescript-eslint. According to its documentation, I need to set up the following:
{
languageOptions: {
parserOptions: {
projectService: true,
tsconfigRootDir: import.meta.dirname,
},
},
},
I updated my ESLint configuration based on the documentation you provided:
// @ts-check
import eslint from "@eslint/js";
import tseslint from "typescript-eslint";
import pluginVue from "eslint-plugin-vue";
import globals from "globals";
export default tseslint.config(
{
extends: [
eslint.configs.recommended,
...tseslint.configs.recommended,
...pluginVue.configs["flat/recommended"],
],
files: ["**/*.{ts,vue}"],
languageOptions: {
ecmaVersion: "latest",
sourceType: "module",
globals: globals.browser,
parserOptions: {
parser: tseslint.parser,
ecmaFeatures: {
jsx: true,
},
projectService: true,
tsconfigRootDir: import.meta.dirname,
},
},
rules: {
// your rules
},
}
);
However, it resulted in an error:
/project/workspace/src/App.vue
0:0 error Parsing error: /project/workspace/src/App.vue was not found by the project service because the extension for the file (`.vue`) is non-standard. You should add `parserOptions.extraFileExtensions` to your config
✖ 1 problem (1 error, 0 warnings)
After configuring parserOptions.extraFileExtensions as suggested by the error message:
/project/workspace/src/App.vue
2:31 error Parsing error: ',' expected
✖ 1 problem (1 error, 0 warnings)
The previous issue still persists.
Is there an incorrect configuration somewhere? How should it be set up to work seamlessly with Typed Linting?
~~You need to add "./**/*.vue" to the "include" option in your tsconfig.json.~~
EDIT: "src/**/*.vue" was already included in the reproduction.
You need to add
"./**/*.vue"to the"include"option in yourtsconfig.json.
You can see the reproduction link I submitted in the issue, where the tsconfig.json configuration is as follows:
{
"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,
"jsx": "preserve",
"jsxImportSource": "vue",
/* Linting */
"strict": true,
"noUnusedLocals": true,
"noUnusedParameters": true,
"noFallthroughCasesInSwitch": true
},
"include": ["src/**/*.ts", "src/**/*.tsx", "src/**/*.vue"],
"references": [{ "path": "./tsconfig.node.json" }]
}
"src/**/*.vue" should already be included.
Even if I add "./**/*.vue" to "include":
/project/workspace/src/App.vue
0:0 error Parsing error: /project/workspace/src/App.vue was not found by the project service because the extension for the file (`.vue`) is non-standard. You should add `parserOptions.extraFileExtensions` to your config
✖ 1 problem (1 error, 0 warnings)
"src/**/*.vue"should already be included.
Oh right.
I have a pretty similar setup (but still on ESLint v8 with .eslintrc.js config format, and without JSX) and it works fine with:
parserOptions: {
parser: {
js: '@typescript-eslint/parser',
ts: '@typescript-eslint/parser',
'<template>': '@typescript-eslint/parser',
},
projectService: {
allowDefaultProject: ['.eslintrc.js', '*.js'],
},
tsconfigRootDir: __dirname,
extraFileExtensions: ['.vue'],
ecmaVersion: 2021,
sourceType: 'module',
},
Maybe it is the JSX that is throwing either parser off somehow?
"src/**/*.vue"should already be included.Oh right.
I have a pretty similar setup (but still on ESLint v8 with
.eslintrc.jsconfig format, and without JSX) and it works fine with:parserOptions: { parser: { js: '@typescript-eslint/parser', ts: '@typescript-eslint/parser', '<template>': '@typescript-eslint/parser', }, projectService: { allowDefaultProject: ['.eslintrc.js', '*.js'], }, tsconfigRootDir: __dirname, extraFileExtensions: ['.vue'], ecmaVersion: 2021, sourceType: 'module', },Maybe it is the JSX that is throwing either parser off somehow?
I haven't encountered this issue on ESLint 8; everything works fine, even with JSX. However, after upgrading to ESLint 9, the problem emerged.
Here is my ESLint 8 configuration, which didn't encounter any issues:
"plugins": ["vue", "@typescript-eslint"],
"parser": "vue-eslint-parser",
"parserOptions": {
"ecmaVersion": 13,
"parser": "@typescript-eslint/parser",
"sourceType": "module",
"ecmaFeatures": {
"jsx": true
}
},
ESLint 9 works fine if I don't configure TypeScript ESLint's Typed Linting. To be honest, I'm not sure where the issue lies.
So you don't have typed linting with ESLint 8? Could you try whether that works?
So you don't have typed linting with ESLint 8? Could you try whether that works?
No, this is the configuration I'm currently using. I'm in the process of migrating from ESLint 8 to ESLint 9, and with ESLint 8, everything was working fine.