ESLint Configuration Best Practices - Complete Guide
Published: September 25, 2024 | Reading time: 25 minutes
ESLint Configuration Overview
Proper ESLint configuration is essential for maintaining code quality and consistency:
ESLint Benefits
# ESLint Configuration Benefits
- Code quality enforcement
- Consistent coding style
- Error prevention
- Team collaboration
- Automated code review
- Best practices enforcement
- Performance optimization
ESLint Setup and Configuration
Basic ESLint Configuration
ESLint Configuration
# ESLint Configuration Best Practices
# 1. Installation and Setup
npm install --save-dev eslint
# Initialize ESLint configuration
npx eslint --init
# Package.json scripts
{
"scripts": {
"lint": "eslint .",
"lint:fix": "eslint . --fix",
"lint:check": "eslint . --max-warnings 0"
}
}
# 2. Basic .eslintrc.js Configuration
module.exports = {
env: {
browser: true,
es2021: true,
node: true
},
extends: [
'eslint:recommended'
],
parserOptions: {
ecmaVersion: 12,
sourceType: 'module'
},
rules: {
// Custom rules
'no-console': 'warn',
'no-unused-vars': 'error',
'prefer-const': 'error'
}
};
# 3. Advanced Configuration with Plugins
module.exports = {
env: {
browser: true,
es2021: true,
node: true,
jest: true
},
extends: [
'eslint:recommended',
'@typescript-eslint/recommended',
'plugin:react/recommended',
'plugin:react-hooks/recommended',
'plugin:jsx-a11y/recommended',
'plugin:import/recommended',
'plugin:import/typescript'
],
parser: '@typescript-eslint/parser',
parserOptions: {
ecmaVersion: 12,
sourceType: 'module',
ecmaFeatures: {
jsx: true
}
},
plugins: [
'react',
'react-hooks',
'jsx-a11y',
'@typescript-eslint',
'import'
],
settings: {
react: {
version: 'detect'
},
'import/resolver': {
typescript: {
alwaysTryTypes: true
}
}
},
rules: {
// TypeScript rules
'@typescript-eslint/no-unused-vars': 'error',
'@typescript-eslint/explicit-function-return-type': 'off',
'@typescript-eslint/explicit-module-boundary-types': 'off',
'@typescript-eslint/no-explicit-any': 'warn',
// React rules
'react/react-in-jsx-scope': 'off',
'react/prop-types': 'off',
'react-hooks/rules-of-hooks': 'error',
'react-hooks/exhaustive-deps': 'warn',
// Import rules
'import/order': ['error', {
'groups': [
'builtin',
'external',
'internal',
'parent',
'sibling',
'index'
],
'newlines-between': 'always'
}],
// General rules
'no-console': 'warn',
'prefer-const': 'error',
'no-var': 'error'
}
};
# 4. Environment-Specific Configuration
// .eslintrc.js
module.exports = {
env: {
browser: true,
es2021: true,
node: true
},
extends: [
'eslint:recommended'
],
parserOptions: {
ecmaVersion: 12,
sourceType: 'module'
},
rules: {
'no-console': process.env.NODE_ENV === 'production' ? 'error' : 'warn',
'no-debugger': process.env.NODE_ENV === 'production' ? 'error' : 'warn'
},
overrides: [
{
files: ['**/*.test.js', '**/*.spec.js'],
env: {
jest: true
},
rules: {
'no-console': 'off'
}
},
{
files: ['**/*.config.js'],
env: {
node: true
},
rules: {
'no-console': 'off'
}
}
]
};
# 5. TypeScript Configuration
// .eslintrc.js for TypeScript
module.exports = {
env: {
browser: true,
es2021: true,
node: true
},
extends: [
'eslint:recommended',
'@typescript-eslint/recommended',
'@typescript-eslint/recommended-requiring-type-checking'
],
parser: '@typescript-eslint/parser',
parserOptions: {
ecmaVersion: 12,
sourceType: 'module',
project: './tsconfig.json'
},
plugins: [
'@typescript-eslint'
],
rules: {
// TypeScript specific rules
'@typescript-eslint/no-unused-vars': ['error', { argsIgnorePattern: '^_' }],
'@typescript-eslint/explicit-function-return-type': 'off',
'@typescript-eslint/explicit-module-boundary-types': 'off',
'@typescript-eslint/no-explicit-any': 'warn',
'@typescript-eslint/no-non-null-assertion': 'warn',
'@typescript-eslint/prefer-nullish-coalescing': 'error',
'@typescript-eslint/prefer-optional-chain': 'error',
// Disable conflicting rules
'no-unused-vars': 'off',
'no-undef': 'off'
}
};
# 6. React Configuration
// .eslintrc.js for React
module.exports = {
env: {
browser: true,
es2021: true,
node: true
},
extends: [
'eslint:recommended',
'plugin:react/recommended',
'plugin:react-hooks/recommended',
'plugin:jsx-a11y/recommended'
],
parserOptions: {
ecmaVersion: 12,
sourceType: 'module',
ecmaFeatures: {
jsx: true
}
},
plugins: [
'react',
'react-hooks',
'jsx-a11y'
],
settings: {
react: {
version: 'detect'
}
},
rules: {
// React rules
'react/react-in-jsx-scope': 'off',
'react/prop-types': 'off',
'react/display-name': 'off',
'react/jsx-uses-react': 'off',
'react/jsx-uses-vars': 'error',
// React Hooks rules
'react-hooks/rules-of-hooks': 'error',
'react-hooks/exhaustive-deps': 'warn',
// Accessibility rules
'jsx-a11y/anchor-is-valid': 'warn',
'jsx-a11y/alt-text': 'error',
'jsx-a11y/aria-props': 'error',
'jsx-a11y/aria-proptypes': 'error',
'jsx-a11y/aria-unsupported-elements': 'error',
'jsx-a11y/role-has-required-aria-props': 'error',
'jsx-a11y/role-supports-aria-props': 'error'
}
};
# 7. Node.js Configuration
// .eslintrc.js for Node.js
module.exports = {
env: {
node: true,
es2021: true
},
extends: [
'eslint:recommended'
],
parserOptions: {
ecmaVersion: 12,
sourceType: 'module'
},
rules: {
// Node.js specific rules
'no-console': 'off',
'no-process-exit': 'error',
'no-sync': 'warn',
// General rules
'prefer-const': 'error',
'no-var': 'error',
'no-unused-vars': ['error', { argsIgnorePattern: '^_' }]
},
overrides: [
{
files: ['**/*.test.js'],
env: {
jest: true
}
}
]
};
# 8. Custom Rules Configuration
// .eslintrc.js with custom rules
module.exports = {
env: {
browser: true,
es2021: true,
node: true
},
extends: [
'eslint:recommended'
],
parserOptions: {
ecmaVersion: 12,
sourceType: 'module'
},
rules: {
// Code quality rules
'complexity': ['warn', 10],
'max-depth': ['warn', 4],
'max-lines': ['warn', 300],
'max-lines-per-function': ['warn', 50],
'max-params': ['warn', 4],
// Style rules
'indent': ['error', 2],
'quotes': ['error', 'single'],
'semi': ['error', 'always'],
'comma-dangle': ['error', 'never'],
'object-curly-spacing': ['error', 'always'],
'array-bracket-spacing': ['error', 'never'],
// Best practices
'eqeqeq': ['error', 'always'],
'no-eval': 'error',
'no-implied-eval': 'error',
'no-new-func': 'error',
'no-return-assign': 'error',
'no-self-compare': 'error',
'no-throw-literal': 'error',
'no-unmodified-loop-condition': 'error',
'no-unused-expressions': 'error',
'no-useless-call': 'error',
'no-useless-concat': 'error',
'no-useless-return': 'error',
'prefer-promise-reject-errors': 'error',
'radix': 'error',
'yoda': 'error'
}
};
# 9. Ignore Patterns
// .eslintignore
node_modules/
dist/
build/
coverage/
*.min.js
*.bundle.js
public/
.env
.env.local
.env.development.local
.env.test.local
.env.production.local
# 10. Package.json Configuration
{
"name": "my-project",
"version": "1.0.0",
"scripts": {
"lint": "eslint . --ext .js,.jsx,.ts,.tsx",
"lint:fix": "eslint . --ext .js,.jsx,.ts,.tsx --fix",
"lint:check": "eslint . --ext .js,.jsx,.ts,.tsx --max-warnings 0",
"lint:staged": "lint-staged"
},
"devDependencies": {
"eslint": "^8.0.0",
"@typescript-eslint/eslint-plugin": "^5.0.0",
"@typescript-eslint/parser": "^5.0.0",
"eslint-plugin-react": "^7.0.0",
"eslint-plugin-react-hooks": "^4.0.0",
"eslint-plugin-jsx-a11y": "^6.0.0",
"eslint-plugin-import": "^2.0.0",
"lint-staged": "^12.0.0"
},
"lint-staged": {
"*.{js,jsx,ts,tsx}": [
"eslint --fix",
"git add"
]
}
}
ESLint Rules and Plugins
Essential ESLint Rules
ESLint Rules Configuration
# ESLint Rules and Plugins
# 1. Code Quality Rules
module.exports = {
rules: {
// Complexity and maintainability
'complexity': ['warn', 10],
'max-depth': ['warn', 4],
'max-lines': ['warn', 300],
'max-lines-per-function': ['warn', 50],
'max-params': ['warn', 4],
'max-statements': ['warn', 20],
// Best practices
'no-console': 'warn',
'no-debugger': 'error',
'no-alert': 'error',
'no-eval': 'error',
'no-implied-eval': 'error',
'no-new-func': 'error',
'no-return-assign': 'error',
'no-self-compare': 'error',
'no-throw-literal': 'error',
'no-unmodified-loop-condition': 'error',
'no-unused-expressions': 'error',
'no-useless-call': 'error',
'no-useless-concat': 'error',
'no-useless-return': 'error',
'prefer-promise-reject-errors': 'error',
'radix': 'error',
'yoda': 'error',
// Variable declarations
'no-unused-vars': ['error', {
argsIgnorePattern: '^_',
varsIgnorePattern: '^_'
}],
'prefer-const': 'error',
'no-var': 'error',
'no-let': 'off',
// Equality
'eqeqeq': ['error', 'always'],
'no-eq-null': 'error',
'no-null': 'off',
// Functions
'func-names': 'off',
'func-style': ['error', 'declaration'],
'no-function-assign': 'error',
'no-inner-declarations': 'error',
'no-new': 'error',
'no-new-wrappers': 'error',
'no-param-reassign': 'error',
'no-redeclare': 'error',
'no-return-await': 'error',
'no-sequences': 'error',
'no-shadow': 'error',
'no-shadow-restricted-names': 'error',
'no-undef': 'error',
'no-undef-init': 'error',
'no-undefined': 'off',
'no-use-before-define': 'error'
}
};
# 2. Style and Formatting Rules
module.exports = {
rules: {
// Indentation
'indent': ['error', 2, {
SwitchCase: 1,
VariableDeclarator: 1,
outerIIFEBody: 1
}],
// Quotes
'quotes': ['error', 'single', {
avoidEscape: true,
allowTemplateLiterals: true
}],
// Semicolons
'semi': ['error', 'always'],
'semi-spacing': ['error', { before: false, after: true }],
// Commas
'comma-dangle': ['error', 'never'],
'comma-spacing': ['error', { before: false, after: true }],
'comma-style': ['error', 'last'],
// Braces
'brace-style': ['error', '1tbs', { allowSingleLine: true }],
'curly': ['error', 'all'],
// Spacing
'object-curly-spacing': ['error', 'always'],
'array-bracket-spacing': ['error', 'never'],
'computed-property-spacing': ['error', 'never'],
'func-call-spacing': ['error', 'never'],
'key-spacing': ['error', { beforeColon: false, afterColon: true }],
'keyword-spacing': ['error', { before: true, after: true }],
'space-before-blocks': ['error', 'always'],
'space-before-function-paren': ['error', 'never'],
'space-in-parens': ['error', 'never'],
'space-infix-ops': 'error',
'space-unary-ops': ['error', { words: true, nonwords: false }],
// Line breaks
'eol-last': ['error', 'always'],
'no-multiple-empty-lines': ['error', { max: 2, maxEOF: 1 }],
'no-trailing-spaces': 'error',
'no-whitespace-before-property': 'error',
'padded-blocks': ['error', 'never'],
// Operators
'operator-linebreak': ['error', 'after'],
'no-mixed-operators': 'error',
'no-multi-spaces': 'error',
'no-multi-str': 'error',
'no-plusplus': 'off',
'no-unneeded-ternary': 'error'
}
};
# 3. Import/Export Rules
module.exports = {
extends: [
'plugin:import/recommended'
],
plugins: [
'import'
],
rules: {
// Import organization
'import/order': ['error', {
'groups': [
'builtin',
'external',
'internal',
'parent',
'sibling',
'index'
],
'newlines-between': 'always',
'alphabetize': {
'order': 'asc',
'caseInsensitive': true
}
}],
// Import restrictions
'import/no-unresolved': 'error',
'import/named': 'error',
'import/default': 'error',
'import/namespace': 'error',
'import/no-absolute-path': 'error',
'import/no-dynamic-require': 'error',
'import/no-internal-modules': 'off',
'import/no-webpack-loader-syntax': 'error',
// Import style
'import/first': 'error',
'import/exports-last': 'off',
'import/no-duplicates': 'error',
'import/no-namespace': 'off',
'import/extensions': ['error', 'ignorePackages'],
'import/no-extraneous-dependencies': 'error',
'import/no-mutable-exports': 'error',
'import/no-unused-modules': 'warn',
'import/unambiguous': 'off',
// Import analysis
'import/no-cycle': 'error',
'import/no-self-import': 'error',
'import/no-useless-path-segments': 'error'
}
};
# 4. TypeScript Rules
module.exports = {
extends: [
'@typescript-eslint/recommended',
'@typescript-eslint/recommended-requiring-type-checking'
],
plugins: [
'@typescript-eslint'
],
rules: {
// TypeScript specific rules
'@typescript-eslint/no-unused-vars': ['error', {
argsIgnorePattern: '^_',
varsIgnorePattern: '^_'
}],
'@typescript-eslint/explicit-function-return-type': 'off',
'@typescript-eslint/explicit-module-boundary-types': 'off',
'@typescript-eslint/no-explicit-any': 'warn',
'@typescript-eslint/no-non-null-assertion': 'warn',
'@typescript-eslint/prefer-nullish-coalescing': 'error',
'@typescript-eslint/prefer-optional-chain': 'error',
'@typescript-eslint/no-unnecessary-type-assertion': 'error',
'@typescript-eslint/no-floating-promises': 'error',
'@typescript-eslint/await-thenable': 'error',
'@typescript-eslint/no-misused-promises': 'error',
'@typescript-eslint/require-await': 'error',
'@typescript-eslint/return-await': 'error',
'@typescript-eslint/prefer-as-const': 'error',
'@typescript-eslint/prefer-includes': 'error',
'@typescript-eslint/prefer-string-starts-ends-with': 'error',
'@typescript-eslint/prefer-readonly': 'error',
'@typescript-eslint/prefer-readonly-parameter-types': 'off',
'@typescript-eslint/prefer-function-type': 'error',
'@typescript-eslint/prefer-interface': 'off',
'@typescript-eslint/consistent-type-definitions': ['error', 'interface'],
'@typescript-eslint/consistent-type-imports': ['error', {
prefer: 'type-imports'
}],
'@typescript-eslint/no-empty-interface': 'error',
'@typescript-eslint/no-extraneous-class': 'error',
'@typescript-eslint/no-inferrable-types': 'error',
'@typescript-eslint/no-magic-numbers': 'off',
'@typescript-eslint/no-parameter-properties': 'error',
'@typescript-eslint/no-require-imports': 'error',
'@typescript-eslint/no-type-alias': 'off',
'@typescript-eslint/no-unnecessary-condition': 'error',
'@typescript-eslint/no-unnecessary-qualifier': 'error',
'@typescript-eslint/no-unnecessary-type-arguments': 'error',
'@typescript-eslint/no-useless-constructor': 'error',
'@typescript-eslint/prefer-for-of': 'error',
'@typescript-eslint/prefer-namespace-keyword': 'error',
'@typescript-eslint/prefer-readonly-parameter-types': 'off',
'@typescript-eslint/prefer-reduce-type-parameter': 'error',
'@typescript-eslint/prefer-ts-expect-error': 'error',
'@typescript-eslint/promise-function-async': 'error',
'@typescript-eslint/require-array-sort-compare': 'error',
'@typescript-eslint/restrict-plus-operands': 'error',
'@typescript-eslint/restrict-template-expressions': 'error',
'@typescript-eslint/strict-boolean-expressions': 'off',
'@typescript-eslint/switch-exhaustiveness-check': 'error',
'@typescript-eslint/typedef': 'off',
'@typescript-eslint/unbound-method': 'error',
'@typescript-eslint/unified-signatures': 'error'
}
};
# 5. React Rules
module.exports = {
extends: [
'plugin:react/recommended',
'plugin:react-hooks/recommended',
'plugin:jsx-a11y/recommended'
],
plugins: [
'react',
'react-hooks',
'jsx-a11y'
],
rules: {
// React specific rules
'react/react-in-jsx-scope': 'off',
'react/prop-types': 'off',
'react/display-name': 'off',
'react/jsx-uses-react': 'off',
'react/jsx-uses-vars': 'error',
'react/jsx-key': 'error',
'react/jsx-no-duplicate-props': 'error',
'react/jsx-no-undef': 'error',
'react/jsx-pascal-case': 'error',
'react/jsx-props-no-multi-spaces': 'error',
'react/jsx-props-no-spreading': 'off',
'react/jsx-sort-props': 'off',
'react/jsx-wrap-multilines': 'error',
'react/no-array-index-key': 'warn',
'react/no-children-prop': 'error',
'react/no-danger': 'warn',
'react/no-danger-with-children': 'error',
'react/no-deprecated': 'error',
'react/no-direct-mutation-state': 'error',
'react/no-find-dom-node': 'error',
'react/no-is-mounted': 'error',
'react/no-render-return-value': 'error',
'react/no-string-refs': 'error',
'react/no-unescaped-entities': 'error',
'react/no-unknown-property': 'error',
'react/no-unsafe': 'error',
'react/no-unused-prop-types': 'error',
'react/no-unused-state': 'error',
'react/prefer-es6-class': 'error',
'react/prefer-stateless-function': 'off',
'react/require-default-props': 'off',
'react/require-render-return': 'error',
'react/self-closing-comp': 'error',
'react/sort-comp': 'off',
'react/sort-prop-types': 'off',
'react/state-in-constructor': 'off',
'react/static-property-placement': 'off',
'react/void-dom-elements-no-children': 'error',
// React Hooks rules
'react-hooks/rules-of-hooks': 'error',
'react-hooks/exhaustive-deps': 'warn',
// Accessibility rules
'jsx-a11y/anchor-is-valid': 'warn',
'jsx-a11y/alt-text': 'error',
'jsx-a11y/aria-props': 'error',
'jsx-a11y/aria-proptypes': 'error',
'jsx-a11y/aria-unsupported-elements': 'error',
'jsx-a11y/click-events-have-key-events': 'warn',
'jsx-a11y/heading-has-content': 'error',
'jsx-a11y/html-has-lang': 'error',
'jsx-a11y/iframe-has-title': 'error',
'jsx-a11y/img-redundant-alt': 'error',
'jsx-a11y/interactive-supports-focus': 'warn',
'jsx-a11y/label-has-associated-control': 'error',
'jsx-a11y/mouse-events-have-key-events': 'warn',
'jsx-a11y/no-access-key': 'error',
'jsx-a11y/no-autofocus': 'warn',
'jsx-a11y/no-distracting-elements': 'error',
'jsx-a11y/no-interactive-element-to-noninteractive-role': 'error',
'jsx-a11y/no-noninteractive-element-interactions': 'warn',
'jsx-a11y/no-noninteractive-element-to-interactive-role': 'error',
'jsx-a11y/no-noninteractive-tabindex': 'error',
'jsx-a11y/no-redundant-roles': 'error',
'jsx-a11y/no-static-element-interactions': 'warn',
'jsx-a11y/role-has-required-aria-props': 'error',
'jsx-a11y/role-supports-aria-props': 'error',
'jsx-a11y/scope': 'error',
'jsx-a11y/tabindex-no-positive': 'error'
}
};
# 6. Performance Rules
module.exports = {
rules: {
// Performance related rules
'no-loop-func': 'error',
'no-new-object': 'error',
'no-new-wrappers': 'error',
'no-array-constructor': 'error',
'no-new-array': 'error',
'no-new-func': 'error',
'no-new-require': 'error',
'no-new-symbol': 'error',
'no-obj-calls': 'error',
'no-octal-escape': 'error',
'no-process-env': 'off',
'no-process-exit': 'error',
'no-proto': 'error',
'no-redeclare': 'error',
'no-regex-spaces': 'error',
'no-restricted-globals': 'error',
'no-restricted-imports': 'off',
'no-restricted-modules': 'off',
'no-restricted-properties': 'off',
'no-restricted-syntax': 'off',
'no-script-url': 'error',
'no-self-compare': 'error',
'no-sequences': 'error',
'no-shadow': 'error',
'no-shadow-restricted-names': 'error',
'no-spaced-func': 'error',
'no-sparse-arrays': 'error',
'no-sync': 'warn',
'no-ternary': 'off',
'no-this-before-super': 'error',
'no-throw-literal': 'error',
'no-trailing-spaces': 'error',
'no-undef': 'error',
'no-undef-init': 'error',
'no-undefined': 'off',
'no-underscore-dangle': 'off',
'no-unexpected-multiline': 'error',
'no-unmodified-loop-condition': 'error',
'no-unneeded-ternary': 'error',
'no-unreachable': 'error',
'no-unsafe-finally': 'error',
'no-unsafe-negation': 'error',
'no-unused-expressions': 'error',
'no-unused-labels': 'error',
'no-unused-vars': 'error',
'no-use-before-define': 'error',
'no-useless-call': 'error',
'no-useless-catch': 'error',
'no-useless-computed-key': 'error',
'no-useless-concat': 'error',
'no-useless-constructor': 'error',
'no-useless-escape': 'error',
'no-useless-rename': 'error',
'no-useless-return': 'error',
'no-var': 'error',
'no-void': 'error',
'no-warning-comments': 'warn',
'no-whitespace-before-property': 'error',
'no-with': 'error',
'object-shorthand': 'error',
'one-var': ['error', 'never'],
'one-var-declaration-per-line': ['error', 'always'],
'operator-assignment': 'error',
'operator-linebreak': ['error', 'after'],
'padded-blocks': ['error', 'never'],
'padding-line-between-statements': 'off',
'prefer-arrow-callback': 'error',
'prefer-const': 'error',
'prefer-destructuring': 'error',
'prefer-numeric-literals': 'error',
'prefer-object-spread': 'error',
'prefer-promise-reject-errors': 'error',
'prefer-reflect': 'off',
'prefer-rest-params': 'error',
'prefer-spread': 'error',
'prefer-template': 'error',
'quote-props': ['error', 'as-needed'],
'quotes': ['error', 'single'],
'radix': 'error',
'require-atomic-updates': 'error',
'require-await': 'error',
'require-jsdoc': 'off',
'require-unicode-regexp': 'error',
'require-yield': 'error',
'rest-spread-spacing': ['error', 'never'],
'semi': ['error', 'always'],
'semi-spacing': ['error', { before: false, after: true }],
'semi-style': ['error', 'last'],
'sort-imports': 'off',
'sort-keys': 'off',
'sort-vars': 'off',
'space-before-blocks': ['error', 'always'],
'space-before-function-paren': ['error', 'never'],
'space-in-parens': ['error', 'never'],
'space-infix-ops': 'error',
'space-unary-ops': ['error', { words: true, nonwords: false }],
'spaced-comment': ['error', 'always'],
'strict': 'off',
'switch-colon-spacing': ['error', { after: true, before: false }],
'symbol-description': 'error',
'template-curly-spacing': ['error', 'never'],
'template-tag-spacing': ['error', 'never'],
'unicode-bom': ['error', 'never'],
'use-isnan': 'error',
'valid-jsdoc': 'off',
'valid-typeof': 'error',
'vars-on-top': 'error',
'wrap-iife': ['error', 'any'],
'wrap-regex': 'off',
'yield-star-spacing': ['error', 'after'],
'yoda': 'error'
}
};
# 7. Custom ESLint Rules
// Custom rule example
module.exports = {
rules: {
// Custom rule for function length
'max-lines-per-function': ['error', {
max: 50,
skipBlankLines: true,
skipComments: true
}],
// Custom rule for file length
'max-lines': ['error', {
max: 300,
skipBlankLines: true,
skipComments: true
}],
// Custom rule for complexity
'complexity': ['warn', 10],
// Custom rule for depth
'max-depth': ['warn', 4],
// Custom rule for parameters
'max-params': ['warn', 4],
// Custom rule for statements
'max-statements': ['warn', 20]
}
};
# 8. ESLint Configuration Validation
// Validation script
const fs = require('fs');
const path = require('path');
function validateESLintConfig() {
const configPath = path.join(process.cwd(), '.eslintrc.js');
if (!fs.existsSync(configPath)) {
console.error('ESLint configuration file not found');
process.exit(1);
}
try {
const config = require(configPath);
// Validate required properties
const requiredProperties = ['env', 'extends', 'parserOptions', 'rules'];
const missingProperties = requiredProperties.filter(prop => !config[prop]);
if (missingProperties.length > 0) {
console.error(`Missing required properties: ${missingProperties.join(', ')}`);
process.exit(1);
}
// Validate rules
const rules = config.rules || {};
const invalidRules = Object.keys(rules).filter(rule => {
const value = rules[rule];
return !Array.isArray(value) && typeof value !== 'string';
});
if (invalidRules.length > 0) {
console.error(`Invalid rule configurations: ${invalidRules.join(', ')}`);
process.exit(1);
}
console.log('ESLint configuration is valid');
} catch (error) {
console.error('Error validating ESLint configuration:', error.message);
process.exit(1);
}
}
validateESLintConfig();
ESLint Integration
ESLint Integration Strategies
ESLint Features
- Code quality rules
- Style enforcement
- Best practices
- Error prevention
- Plugin ecosystem
- Custom rules
- IDE integration
Configuration Areas
- Environment setup
- Parser configuration
- Rule customization
- Plugin management
- Override patterns
- Ignore patterns
- Performance optimization
Summary
ESLint configuration best practices involve several key areas:
- Setup: Proper installation, initialization, and environment configuration
- Rules: Code quality, style, and best practice enforcement
- Plugins: TypeScript, React, accessibility, and import management
- Integration: IDE integration, pre-commit hooks, and CI/CD pipelines
Need More Help?
Struggling with ESLint configuration or need help setting up comprehensive code quality rules? Our JavaScript experts can help you implement effective linting strategies.
Get ESLint Help