← Back to list

ESlint V9 Flatconfig

This article starts with explanation on ESLint and deep dives into the flatConfig structure which is the default structure in ESLint V9

Sofiya Sundaramoorthy · 2025-01-19 11:01 · 0 claps · 2.4 min read
#eslint-configuration #typescript #angular #flatconfig
Open on Medium ↗
Wiki topics: 🌐 · Web Development

ESlint V9 Flatconfig

This article starts with explanation on ESLint and deep dives into the flatConfig structure which is the default structure in ESLint V9

ESLint

Eslint is a generic linting tool to find any problematic patterns in javascriptcode. It is used across javascriptframeworks and languages.

Supports multiple files including Javascript , Typescript, and JSX . More info

Typescript ESLint

Typescript ESLint is an extension of ESLint specifically for Typescript . It provides Typescript specific linting rules built on top of ESLint .

More info

Angular ESLint

Angular ESLint is a set of tools that enables ESLint for Angular projects. It combines ESLintrules along with Angular specific configuration and rules . It also provides Angular template linting capabilities.

More info

Major features in ESLint V9

  1. Performance

— quiet flag now ignores execution on rules set to warn thus increasing the build time of the application.

  1. Simplicity

ESLint configuration is simplified with flat config structure which supports .cjs .mjs and .js as opposed to .yml , .json structure in their previous versions

Removed Properties:

Global ignoresPattern is replaced with ignores in individual config object

Plugins no longer take string based key-value pair. It is now an object configuration

Caveat: .mjsformat is not yet supported in NX (at the time of writing this article (Jan 2025)

Configuration for Angular project: (eslint.config.cjs)

const importPlugins = require('eslint-plugin-import');
const eslintTs = require('typescript-eslint');
const angular = require('angular-eslint');
const nx = require('@nx/eslint-plugin');
const unusedImportsPlugin = require('eslint-plugin-unused-imports');
const prettierPlugin = require('eslint-plugin-prettier');
const eslintPrettierPlugin = require('eslint-config-prettier');

const tsFiles = ['**/*.ts'];

const ignores = [
  '/build/**', 
  '/reports/**', 
  '**/dist/**',
  '**/node_modules/**',
  '**/.storybook/**',
  'jest.config.ts',
  '!apps/demo/src/**/*.ts' 
];

const languageOptions = {
  globals: {
    // add global env variables in future
  }
}

const jsonConfig = {
  files: ['**/*.json'],
  // Override or add rules here
  rules: {},
  languageOptions: {
   parser: require('jsonc-eslint-parser')
  }
}

const tsConfig = {
  files: tsFiles,
  plugins: {
    import: importPlugins,
    'import/parser': eslintTs.parser,
    '@nx': nx,
    'unused-imports': unusedImportsPlugin,
    prettier: prettierPlugin
  },
  languageOptions: {
    ...languageOptions,
    parser: eslintTs.parser,
    parserOptions: {
      project: './tsconfig.eslint.json'
    }
  },
  settings: {
    'import/parsers': {
        '@typescript-eslint/parser': ['.ts'],
    },
  },
  rules: {
    "unused-imports/no-unused-imports": "error",
    'import/order': [
      'error',
      {
        'groups': ["builtin", "external", "internal", "parent", "sibling", "index", "object", "type"]
      }
    ],
    'import/export': 'error',
    'import/no-duplicates': 'warn',
    ...importPlugins.configs.typescript.rules,
    '@typescript-eslint/no-use-before-define': 'off',
    'require-await': 'off',
    'no-duplicate-imports': 'error',
    'no-unneeded-ternary': 'error',
    'prefer-object-spread': 'error',
    '@typescript-eslint/no-unused-vars': [
        'error',
        {
            ignoreRestSiblings: true,
            args: 'none',
        },
    ],
    '@typescript-eslint/naming-convention': [
        'error',
        {
          selector: 'interface',
          format: ['PascalCase'],
          custom: {
            regex: '^I[A-Z]',
            match: false
          }
        },
        {
          selector: 'class',
          format: ['PascalCase']
        },
        {
          selector: 'typeAlias',
          format: ['PascalCase'],
          custom: {
            regex: '^T[A-Z]',
            match: false
          }
        }
    ],
    // overriding rules provided by angular-eslint
    '@angular-eslint/no-input-rename': 'off',
    '@angular-eslint/component-class-suffix': 1,
    '@angular-eslint/directive-class-suffix': 1,
    '@angular-eslint/no-output-on-prefix': 'warn',
    '@angular-eslint/no-output-native': 'warn',
    '@nx/nx-plugin-checks': 'error',
    ...prettierPlugin.configs.recommended.rules,
    ...eslintPrettierPlugin.rules
  }
}

// Add the files for applying the recommended TypeScript configs 
// only for the Typescript files.
// This is necessary when we have the multiple extensions files 
// (e.g. .ts, .tsx, .js, .cjs, .mjs, etc.).
const recommendedTypeScriptConfigs = [
  ...eslintTs.configs.recommended.map((config) => ({
      ...config,
      files: tsFiles,
  })),
  ...eslintTs.configs.stylistic.map((config) => ({
      ...config,
      files: tsFiles,
  }))
]

const recommendedAngularConfigs = [
  ...angular.configs.tsRecommended.map((config) => ({
    ...config,
    files: tsFiles
  })),
  ...angular.configs.templateRecommended.map((config) => ({
    ...config,
    files: ['**/*.html'],
  })),
  ...angular.configs.templateAccessibility.map((config) => ({
    ...config,
    files: ['**/*.html']
  }))
]

const recommendedNXConfigs = [
  ...nx.configs['flat/base'],
  ...nx.configs['flat/typescript'].map((config) => ({
    ...config,
    files: tsFiles
  })),
  ...nx.configs['flat/angular'].map((config) => ({
    ...config,
    files: tsFiles
  }))
]

module.exports = [
  { ignores }, // global ignores
  ...recommendedTypeScriptConfigs,
  ...recommendedAngularConfigs,
  ...recommendedNXConfigs, // all the typescript and angular rules gets overriden by NX specific typescript and angular rules
  tsConfig,
  jsonConfig
]

메타데이터
post_id
8a4faa1059e6
slug
eslint-v9-flatconfig-8a4faa1059e6
url
https://medium.com/@sofiyanaidu/eslint-v9-flatconfig-8a4faa1059e6
canonical_url
https://medium.com/@sofiyanaidu/eslint-v9-flatconfig-8a4faa1059e6
author_url
https://medium.com/@sofiyanaidu
status
ok
fetched_at
2026-07-28 16:12:54