vue.jseslinttypescript-eslint

Eslint 9 with typescript and vue error on defineEmits


after upgrading the dependencies of my astro blog, I've stumbled across a strange problem with the newest eslint version and typescript + vue.

I followed the official docs of eslint, tslint, eslint-plugin-vue and eslint-config-prettier, however something is strange and I don't know why.

Eslint is telling me that this codeblock has a parsing error Parsing error: Unexpected token, however this should be ok (see the official vue docs)

<script setup lang="ts">
const emit = defineEmits<{
  (e: 'change', id: number): void
  (e: 'update', value: string): void
}>()
</script>

I've provided a minimal example https://github.com/Theiaz/eslint-defineemits-bug for the error. Seems like the config for vue is not loaded correctly. What am I missing here?

{
  "name": "typescript-eslint-vue",
  "version": "0.0.0",
  "private": true,
  "type": "module",
  "scripts": {
    "check": "vue-tsc --noEmit && tsc --noEmit ",
    "lint": "eslint --fix src"
  },
  "devDependencies": {
    "@eslint/js": "^9.13.0",
    "@types/eslint__js": "^8.42.3",
    "@typescript-eslint/parser": "^8.11.0",
    "eslint": "^9.13.0",
    "eslint-config-prettier": "^9.1.0",
    "eslint-plugin-vue": "^9.10.0",
    "prettier": "^3.3.3",
    "typescript": "^5.6.3",
    "typescript-eslint": "^8.11.0",
    "vue": "^3.5.12",
    "vue-tsc": "^2.1.6"
  },
  "dependencies": {
    "@vue/tsconfig": "^0.5.1",
    "@vueuse/core": "^11.1.0"
  }
}
import eslint from "@eslint/js";
import prettierConfig from "eslint-config-prettier";
import pluginVue from "eslint-plugin-vue";
import tseslint from "typescript-eslint";

export default tseslint.config(
  eslint.configs.recommended,
  ...tseslint.configs.recommended,
  ...pluginVue.configs["flat/recommended"],
  prettierConfig,
  {
    files: ["**/*.ts", "**/*.vue"],
    rules: {},
  }
);

Solution

  • The current config misses the configuration of Vue ELint parser, as suggested in the documentation:

    import vueParser from 'vue-eslint-parser';
    
    export default tseslint.config(
      eslint.configs.recommended,
      ...tseslint.configs.recommended,
      ...pluginVue.configs["flat/recommended"],
      prettierConfig,
      {
        files: ["**/*.ts", "**/*.vue"],
        rules: {},
        languageOptions: {
          parser: vueParser,
          parserOptions: {
            parser: {
              ts: tseslint.parser,
      ...
    

    @vue/eslint-config-typescript can be used to correctly configure ESlint to work with TypeScript and Vue SFC:

    import pluginVue from "eslint-plugin-vue";
    import vueTsEslintConfig from "@vue/eslint-config-typescript";
    
    export default [
      ...pluginVue.configs["flat/essential"],
      ...vueTsEslintConfig(),
      // Add prettier or else
    ]
    

    This eliminates the need to use typescript-eslint directly and provides sensible defaults.