Applying the automatic fix for non-null assertions removes a character from the wrong place. It seems related to #2591 and #2680 where vue-eslint-parser alters the locations information for every node it produces within a script tag, but it doesn't know about the typescript nodes, so their range information is wrong. The fix is being applied as if there was no script tag. You can see that by running the lint command without the --fix flag, the eslint command output reports the error at an incorrect line or character index.
Repro
Steps:
- Create a simple Vue 3 single file component like below. This component unnecessarily does type assertion on the string literal.
<script setup lang="ts">
const test = 'foobar'.length!
</script>
<template>
<div></div>
<template>
- Apply linting with
--fix flag and with the rule enabled. See package.json/.eslintrc examples below. I am using latest versions of vue-eslint-plugin, this TS parser, this TS plugin, and Eslint.
- When linting completes, the letter "t" is removed from
const and not the unnecessary non-null assertion.
module.exports = {
env: {
browser: true,
es6: true,
'vue/setup-compiler-macros': true
},
plugins: ['@typescript-eslint'],
parser: 'vue-eslint-parser',
parserOptions: {
parser: '@typescript-eslint/parser',
project: '**/tsconfig.json',
sourceType: 'module',
extraFileExtensions: ['.vue']
},
extends: [
'eslint:recommended',
'plugin:@typescript-eslint/recommended',
'plugin:@typescript-eslint/recommended-requiring-type-checking',
'plugin:vue/essential',
'prettier'
],
rules: {
'@typescript-eslint/ban-types': 'off',
'@typescript-eslint/no-namespace': 'off',
'@typescript-eslint/adjacent-overload-signatures': 'off',
'@typescript-eslint/prefer-regexp-exec': 'off',
'@typescript-eslint/no-unsafe-call': 'off',
'@typescript-eslint/no-unsafe-assignment': 'off',
'@typescript-eslint/no-unsafe-member-access': 'off',
'@typescript-eslint/no-unsafe-return': 'off',
'@typescript-eslint/restrict-template-expressions': 'off'
}
};
{
"name": "foobar",
"version": "0.0.1",
"scripts": {
"lint:js": "eslint src --ext .js,.ts,.vue --quiet",
"lint:js:fix": "eslint src --ext .js,.ts,.vue --fix --quiet"
},
"dependencies": {
"vue": "^3.2.25"
},
"devDependencies": {
"@typescript-eslint/eslint-plugin": "^5.16.0",
"@typescript-eslint/parser": "^5.16.0",
"eslint": "^8.11.0",
"eslint-config-prettier": "^8.3.0",
"eslint-plugin-vue": "^8.5.0",
"typescript": "^4.4.3",
"vue-eslint-parser": "^8.3.0"
}
}
Expected Result
See that the non-null assertion was removed.
<script setup lang="ts">
const test = 'foobar'.length
</script>
<template>
<div >
<template>
Actual Result
See that the letter 't' was removed from const.
<script setup lang="ts">
cons test = 'foobar'.length!
</script>
<template>
<div >
<template>
Additional Info
It looks like a similar issue was identified in #2591. And a fix was applied in #2680.
Versions
| package |
version |
@typescript-eslint/eslint-plugin |
5.16.0 |
@typescript-eslint/parser |
5.16.0 |
TypeScript |
4.4.3 |
ESLint |
8.11.0 |
node |
17.3.1 |
Applying the automatic fix for non-null assertions removes a character from the wrong place. It seems related to #2591 and #2680 where
vue-eslint-parseralters the locations information for every node it produces within a script tag, but it doesn't know about the typescript nodes, so their range information is wrong. The fix is being applied as if there was no script tag. You can see that by running the lint command without the--fixflag, the eslint command output reports the error at an incorrect line or character index.Repro
Steps:
--fixflag and with the rule enabled. Seepackage.json/.eslintrcexamples below. I am using latest versions ofvue-eslint-plugin, this TS parser, this TS plugin, and Eslint.constand not the unnecessary non-null assertion.{ "name": "foobar", "version": "0.0.1", "scripts": { "lint:js": "eslint src --ext .js,.ts,.vue --quiet", "lint:js:fix": "eslint src --ext .js,.ts,.vue --fix --quiet" }, "dependencies": { "vue": "^3.2.25" }, "devDependencies": { "@typescript-eslint/eslint-plugin": "^5.16.0", "@typescript-eslint/parser": "^5.16.0", "eslint": "^8.11.0", "eslint-config-prettier": "^8.3.0", "eslint-plugin-vue": "^8.5.0", "typescript": "^4.4.3", "vue-eslint-parser": "^8.3.0" } }{ "compilerOptions": { "baseUrl": ".", "esModuleInterop": true, "jsx": "preserve", "lib": ["esnext", "dom"], "module": "esnext", "moduleResolution": "node", "noImplicitAny": false, "paths": { "@/*": ["src/*"] }, "resolveJsonModule": true, "sourceMap": true, "strict": true, "target": "esnext", "types": ["vite/client", "@types/jest"] }, "include": ["src/**/*.ts", "src/**/*.vue"] }Expected Result
See that the non-null assertion was removed.
Actual Result
See that the letter 't' was removed from
const.Additional Info
It looks like a similar issue was identified in #2591. And a fix was applied in #2680.
Versions
@typescript-eslint/eslint-plugin5.16.0@typescript-eslint/parser5.16.0TypeScript4.4.3ESLint8.11.0node17.3.1