Skip to content

ESLint Flat Configuration for Vue 3 and TypeScript Projects

Problem Statement

Setting up ESLint 9's new flat configuration format (eslint.config.js) in Vue 3 projects using TypeScript presents several challenges:

  • Legacy ESLint configuration patterns don't migrate cleanly to the flat config system
  • Vue files require special parser configurations for both template syntax and TypeScript
  • Combining TypeScript and Vue plugins requires careful configuration to avoid parser conflicts
  • Prettier integration must be preserved in the new format
  • VSCode requires specific configuration changes with flat config

Without proper setup, developers face linting errors in Vue files, TypeScript-specific issues going undetected, or formatting conflicts between ESLint and Prettier.

Solution Approach

This guide provides a comprehensive configuration that combines:

  • TypeScript ESLint (typescript-eslint)
  • Vue template linting (eslint-plugin-vue)
  • Prettier compatibility (eslint-config-prettier)

Key considerations:

  • Use only one Vue plugin config (flat/recommended includes all base rules)
  • Configure nested parsers for TypeScript in Vue SFCs
  • Maintain proper Prettier disabling order
  • Update TypeScript configuration to include Vue files
  • Modify VSCode settings for flat config support

Prerequisites

bash
npm install eslint @eslint/js typescript-eslint eslint-plugin-vue eslint-config-prettier --save-dev

Step-by-Step Configuration

1. Minimal tsconfig.json

json
{
  "extends": "@vue/tsconfig/tsconfig.dom.json",
  "include": ["src/**/*.ts", "src/**/*.d.ts", "src/**/*.tsx", "src/**/*.vue"]
}

2. ESLint Configuration (eslint.config.js)

javascript
import eslint from '@eslint/js';
import tseslint from 'typescript-eslint';
import pluginVue from 'eslint-plugin-vue';
import eslintConfigPrettier from 'eslint-config-prettier';

export default tseslint.config(
  // Global ignores
  {
    ignores: [
      'dist/**',
      'node_modules/**',
      '**/cypress/**',
      'coverage/**'
    ]
  },
  
  // Base JavaScript and TypeScript rules
  eslint.configs.recommended,
  {
    files: ['**/*.{js,ts,jsx,tsx,vue}'],
    languageOptions: {
      ecmaVersion: 'latest',
      sourceType: 'module',
    }
  },
  
  // TypeScript-specific configuration
  ...tseslint.configs.recommended,
  {
    files: ['**/*.{ts,tsx}'],
    languageOptions: {
      parser: tseslint.parser,
      parserOptions: {
        project: true,
      }
    }
  },
  
  // Vue file configuration with TypeScript support
  ...pluginVue.configs['flat/recommended'],
  {
    files: ['**/*.vue'],
    languageOptions: {
      parserOptions: {
        parser: tseslint.parser,
        project: './tsconfig.json',
        extraFileExtensions: ['.vue'],
        sourceType: 'module',
      }
    },
    rules: {
      // Custom Vue rules
      'vue/match-component-import-name': 'warn',
      'vue/match-component-file-name': [
        'error',
        { extensions: ['vue'], shouldMatchCase: true }
      ],
      'vue/component-definition-name-casing': ['error', 'PascalCase'],
      'vue/block-tag-newline': [
        'warn', 
        { singleline: 'always', multiline: 'always', maxEmptyLines: 0 }
      ],
      'vue/require-default-prop': 'off'
    }
  },
  
  // Prettier compatibility (MUST be last)
  eslintConfigPrettier
);

Key Configuration Notes

Vue + TypeScript Parser Setup

The critical parser configuration enables both Vue template parsing and TypeScript type checking:

javascript
languageOptions: {
  parserOptions: {
    parser: tseslint.parser,      // Parses TypeScript inside <script> blocks
    project: './tsconfig.json',   // Path to your TypeScript config
    extraFileExtensions: ['.vue'] // Allow type checking for .vue files
  }
}

Avoid Config Duplication

Do not combine multiple Vue plugin configs. flat/recommended includes:

  • flat/essential
  • flat/strongly-recommended
  • Additional recommended rules

Using multiple configurations causes rule conflicts and duplication.

VSCode Setup

Add to your settings.json:

json
{
  "eslint.experimental.useFlatConfig": true
}

These rules improve Vue+TypeScript development:

javascript
rules: {
  // Ensure PascalCase for component names
  'vue/component-name-in-template-casing': ['error', 'PascalCase'],
  
  // Relax prop requirements when using TypeScript
  'vue/require-prop-types': 'off',
  'vue/require-default-prop': 'off',
  
  // Modern TypeScript practices
  '@typescript-eslint/no-explicit-any': 'warn',
  '@typescript-eslint/consistent-type-imports': 'error'
}

Debugging Tips

Common Issues Fixes

  1. "Parsing error" in Vue files:

    • Verify parserOptions.parser points to @typescript-eslint/parser
    • Confirm extraFileExtensions: ['.vue'] is set
  2. "Missing type information" errors:

    • Ensure your tsconfig.json includes Vue files
    • Check paths in project config match your setup
  3. Prettier conflicts:

    • Confirm eslint-config-prettier is applied last
    • Remove conflicting rules from other configs

Migration Helpers

To troubleshoot configuration:

bash
npx eslint --print-config example.vue

Final Recommendations

  1. Use vue-eslint-parser version 9.5+ for Vue 3 support
  2. Update all ESLint plugins to their latest versions
  3. Verify TypeScript 5.x compatibility with all plugins
  4. Convert legacy rules to new naming format where needed

Version Alert

As of September 2024, these packages are confirmed compatible with ESLint 9:

  • eslint-plugin-vue: v9.22.0+
  • typescript-eslint: v8.0.0+

Maintenance Notes

Review these documentation sources regularly: