vue-cli: Typescript-Eslint conflict
Version
3.0.0-rc.3
Reproduction link
https://github.com/marcus-blaettermann-ventoro/vue-cli-bug/tree/master
Steps to reproduce
Clone the given repo, npm install and then npm run lint
Alternative: Run vue create with those settings:
Vue CLI v3.0.0-rc.3
? Please pick a preset: Manually select features
? Check the features needed for your project: Babel, TS, Linter
? Use class-style component syntax? No
? Use Babel alongside TypeScript for auto-detected polyfills? No
? Pick a linter / formatter config: Airbnb
? Pick additional lint features: Lint on save
? Where do you prefer placing config for Babel, PostCSS, ESLint, etc.? In dedicated config files
? Save this as a preset for future projects? (y/N)
Then add this to the src/components/Hello-World.vue:
enum Direction {
Up,
Down,
}
const foo: Direction = Direction.Up;
What is expected?
The linter should not find any errors, or at least should fix the errors it finds.
What is actually happening?
The linter adds a space before one of the commas in the enum Direction and then complains about it. Removing the space has no effect because the linter adds it the next time again. When using lint on save in an editor, the comma jumps between the first and second line.
- This has been reproduced on both Mac and Windows.
- The problem doesn`t occure with the same code in a regular .ts file
- The problem only occurs, when an enum (something regular JavaScript doesn`t have) followed by something with a type declaration.
- The problem also occurs, when the enum is in a single line.
enum Direction { Up, Down } - If the
const foo : Direction = Direction.Up;is removed the linter doesn`t mind the enum anymore. - I think the linter somehow chokes on the type declaration colon.
About this issue
- Original URL
- State: closed
- Created 6 years ago
- Reactions: 3
- Comments: 17 (12 by maintainers)
Commits related to this issue
- fix: temporarily disable space-infix-ops for eslint + TS ref #1672 — committed to vuejs/vue-cli by yyx990803 6 years ago
- chore(eslint): disable typescript eslint conflict rules https://github.com/vuejs/vue-cli/issues/1672 — committed to MoePlayer/vue-aplayer by u3u 6 years ago
- chore(eslint): disable typescript eslint conflict rules https://github.com/vuejs/vue-cli/issues/1672 — committed to hitokoto-osc/vue-aplayer by u3u 6 years ago
Hi.
Recently, I fixed several bugs in
typescript-eslint-parser: https://github.com/eslint/typescript-eslint-parser/pull/540Also, I added the support of
typescript-eslint-parserinto our online demo: https://mysticatea.github.io/vue-eslint-demo/Would you confirm whether the problem was fixed or not?
Oh boy, I went through
typescript-eslint-parser,eslintandvue-eslint-parserinternals, but finally I know what’s going on 😅So:
typescript-eslint-parserproduces new propertytypeAnnotationon some nodes in the AST with dedicated token - calledTSTypeAnnotationvue-eslint-parserin this scenario uses parser service offered bytypescript-eslint-parserto get the enhanced ASTvue-eslint-parser, due to the fact that we’re parsing.vuefiles and script tag is usually placed somewhere belowtemplateis to update locations and ranges of all tokens in the AST, so that errors produced byeslintpoint to exact place in our.vuefile.vue-eslint-parserdoesn’t know anything about these new types of tokens, and doesn’t update their ranges.space-infix-opsrule happens to handle case with this typeAnnotation, and if it detects this annotation it takes this exact node and based on it’s range and range of the former tag finds all tokens that happens to be within the calculated rangeTSTypeAnnotationtype has wrong range - it reports wrongly discovered tokens, hence the error pointed in the description.I’m going to come up with the fix as soon as I can 😃
Fun fact: You can fix it by placing
<script>tag at the top of your.vuefile 😃I just confirmed this issue, and did some digging in ASTs. Looks like the produced AST for the
<script>tag inside.vuefile is almost identical to what is produced by plain.tsfile. Almost - because one thing differs and causes the problem. In.vueAST there are extra circularparentnodes. In effect - whenever eslint meetsVariableDeclaratorit’ll search through the whole range of tokens inside the file, whereas in.tsthere is no parrent to corrupt token search range.In ESlint v5 the
parentnode behaviour has slightly changed and now the parent node is being set before we even have access to the AST in eslint rules. I’ll try to investigate it a bit more, but it looks like the AST for.vuemight be the proper one given those changes and the problem might be in thespace-infix-opsrule itself. Also we may have another problem - that plain javascript files are not being parsed consistently if it happens to be true.I’ll post an update once I know more. These are my first insights.
@mysticatea I can confirm it’s working now. Thank you.