create-vue
create-vue copied to clipboard
eslint: @typescript-eslint error when add some rules
-
Create vue 2 project using following config
-
npm install
-
add rules inside
.eslintrc.cjs
rules: { "@typescript-eslint/prefer-optional-chain": "error" }
-
npm run lint
-
terminal error
Error: Error while loading rule '@typescript-eslint/prefer-optional-chain': You have used a rule which requires parserServices to be generated. You must therefore provide a value for the "parserOptions.project" property for @typescript-eslint/parser.
FYI.
Adding parserOptions: { project: ["tsconfig.json"] }
to .eslintrc.cjs
won't help.
Maybe caused by eslint-plugin-vue
or @typescript-eslint
related https://github.com/vuejs/vue-eslint-parser/issues/104#issuecomment-909082288
This is kinda complicated…
I've got a working configuration:
.eslintrc.cjs
:
/* eslint-env node */
require("@rushstack/eslint-patch/modern-module-resolution");
module.exports = {
root: true,
extends: [
"plugin:vue/vue3-essential",
"eslint:recommended",
"@vue/eslint-config-typescript/recommended",
"@vue/eslint-config-prettier",
],
rules: {
"@typescript-eslint/prefer-optional-chain": "error",
},
parserOptions: {
parser: "@typescript-eslint/parser",
project: "./tsconfig.json",
},
overrides: [
{
files: ["vite.config.ts", ".eslintrc.cjs"],
parserOptions: {
parser: "@typescript-eslint/parser",
project: "./tsconfig.config.json",
},
},
],
};
And add ".eslintrc.cjs"
to the "include"
array in tsconfig.config.json
.
The trick here is that we can only have a single parser
when project
is used, thus the parser
object set in @vue/eslint-config-typescript
must be overriden https://github.com/vuejs/eslint-config-typescript/blob/75a6bde42c6aadc805d01f23bed23c0a9f2e4ada/index.js#L9-L17
And since we use solution-style tsconfigs in the project, some files in the project aren't covered by the root tsconfig.json
, so we need to configure overrides
for them. In this case, it's vite.config.ts
and .eslintrc.cjs
.
It works, thanks! Should this be in doc or as a built-in?
It seems tsx
failed to parse
<script lang="tsx">
import { defineComponent } from "vue";
export default defineComponent({
render() {
return <div></div>; // Parsing error: Type expected.
},
});
</script>
Yeah, currently it seems not possible to use project
with script lang="tsx"
in .vue
files:
parserOptions.ecmaFeatures.jsx
- ...
- For "unknown" extensions (
.md
,.vue
):
- If
parserOptions.project
is not provided:
- The setting will be respected.
- If
parserOptions.project
is provided (i.e. you are using rules with type information):
- always parsed as if this is
false
https://github.com/typescript-eslint/typescript-eslint/blob/main/packages/parser/README.md#parseroptionsecmafeaturesjsx
So it's impossible to make everything works for now?
I may disable those @typescript-eslint
rules that requires project
.
I'm afraid so 🙁
It was the limitation of typescript-eslint
or eslint-plugin-vue
or eslint
itself?
If we can specify project
for parserOptions.parser.ts
, the problem maybe solved. But we can't as https://github.com/vuejs/vue-eslint-parser/issues/104#issuecomment-896638158 said.
"parserOptions": {
"parser": {
"ts": "@typescript-eslint/parser",
"<template>": "espree"
}
}
I'm not sure.
But from the description, that it works without project
, I guess it's a limitation of TypeScript itself.
Because TypeScript never supports custom file extensions well. For example, to make TypeScript work well with .vue
files, we have to use a custom command-line tool: https://github.com/johnsoncodehk/volar/tree/master/packages/vue-tsc
Maybe @typescript-eslint
can make it work by using the vue-tsc
version of the TypeScript language service instead of the official one. But it's only my guess; I'm not familiar with either tool's actual implementation.
What a pity, disable rule @typescript-eslint/prefer-optional-chain
could be the most acceptable result.
Should I leave this issue open?
Yeah, let's leave it open until I find a better place to document this limitation.
Oh I forgot to mention that I used to use the old version @vue/[email protected]
with [email protected]
and it worked.
Though new features like defineProps
are not recognized.
/* eslint-env node */
require('@rushstack/eslint-patch/modern-module-resolution')
module.exports = {
root: true,
env: {
node: true,
},
extends: [
'plugin:vue/essential',
'eslint:recommended',
'@vue/typescript/recommended', // this line was changed
'@vue/eslint-config-prettier',
],
rules: {
'@typescript-eslint/prefer-optional-chain': 'error',
},
}
Oh I forgot to mention that I used to use the old version
@vue/[email protected]
with[email protected]
and it worked.
It might be caused by https://github.com/typescript-eslint/typescript-eslint/pull/4430 that triggers an undefined behavior in .vue
files https://github.com/typescript-eslint/typescript-eslint/issues/4755#issuecomment-1080961338
FYI, I just created a @vue/eslint-config-standard-with-typescript
package.
https://github.com/vuejs/eslint-config-standard/tree/main/packages/eslint-config-standard-with-typescript#readme
By default it only supports <script lang="ts">
in .vue
, but you can opt-in to use other lang
s (not encouraged).
You can take that as a reference.
I plan to do similar refactors in @vue/eslint-config-airbnb
and @vue/eslint-config-typescript
later, but that would require much more time, because there are too many rules.
There are many other rules require project
to be set, you can search getParserServices
usage inside https://github.com/typescript-eslint/typescript-eslint/tree/main/packages/eslint-plugin/src/rules
to get the full list :)
This isn't an exact solution for vue.js, but for anyone coming here from search looking to solve this problem for ts-node or node based typescript, I was able to solve the "You have used a rule which requires parserServices to be generated" error as follows (local setup: node 18-lts):
Add tsconfig.json
and .eslintrc.js
to your .eslintignore
. If on vscode, you may want to add .vscode/settings.json
as well.
Then in your .eslintrc
file, add a settings
prop and here is the config I am using (you likely do not need all the plugins I am using):
{
"parser": "@typescript-eslint/parser",
"extends": [
"plugin:@typescript-eslint/recommended",
"plugin:import/recommended",
"plugin:eslint-comments/recommended",
"plugin:jsonc/recommended-with-jsonc"],
"parserOptions": {
"ecmaVersion": "latest",
"sourceType": "module"
},
"plugins": ["unicorn","@typescript-eslint"],
"settings": {
"import/resolver": {
"node": { "extensions": [".js", ".mjs", ".ts", ".d.ts"] },
"typescript": {
"project": "./tsconfig.json"
}
}
},
"rules" : { ... }
}
This does not follow any instructions or guides I have found via Google, and yet it is the only solution I've found that actually works.
Your mileage may vary, but this worked for me. Also, remember to restart eslint after making this change (cmd+shift+p
and then restart eslint
)
just another fyi, if you have this working but the error crops up anyway, make sure that you have a <script></script>
part in your sfc, even if it's empty.