تخطَّ إلى المحتوى

ESLint Cheat Sheet

Overview

ESLint is the standard linting tool for JavaScript and TypeScript projects. It statically analyzes code to find problems, enforce coding conventions, and automatically fix many issues. ESLint uses a pluggable rule architecture where every rule is a standalone module, and developers can create and share their own rules and configurations.

ESLint 9 introduced a flat configuration system (eslint.config.js) that replaces the legacy .eslintrc format. The new config is simpler, uses native JavaScript modules, and provides better control over which files each rule applies to. ESLint integrates with all major editors and CI/CD pipelines.

Installation

# Initialize ESLint in a project (interactive setup)
npm init @eslint/config@latest

# Or install manually
npm install -D eslint

# Install TypeScript support
npm install -D typescript-eslint @typescript-eslint/parser

# Install popular plugins
npm install -D eslint-plugin-react eslint-plugin-react-hooks
npm install -D eslint-plugin-import
npm install -D eslint-plugin-jsx-a11y

# Global install (not recommended)
npm install -g eslint

Core Commands

CommandDescription
npx eslint .Lint all files in current directory
npx eslint src/Lint specific directory
npx eslint file.jsLint a specific file
npx eslint --fix .Auto-fix fixable issues
npx eslint --fix-dry-run .Show what —fix would change
npx eslint --debug .Show debug information
npx eslint --print-config file.jsShow resolved config for a file
npx eslint --cache .Use cache for faster re-runs
npx eslint --max-warnings 0 .Fail on any warnings
npx eslint --format stylish .Use specific output formatter

Output Formats

# Built-in formatters
npx eslint --format stylish .       # Default colored output
npx eslint --format json .          # JSON output
npx eslint --format compact .       # Single-line per issue
npx eslint --format html .          # HTML report
npx eslint --format unix .          # Unix-style output

Configuration

Flat Config (ESLint 9+)

// eslint.config.js
import js from "@eslint/js"
import globals from "globals"
import tseslint from "typescript-eslint"
import reactPlugin from "eslint-plugin-react"
import reactHooks from "eslint-plugin-react-hooks"

export default [
  // Base recommended rules
  js.configs.recommended,

  // TypeScript rules
  ...tseslint.configs.recommended,

  // Global settings
  {
    languageOptions: {
      ecmaVersion: 2025,
      sourceType: "module",
      globals: {
        ...globals.browser,
        ...globals.node,
      },
      parserOptions: {
        ecmaFeatures: { jsx: true },
      },
    },
  },

  // React rules
  {
    plugins: {
      react: reactPlugin,
      "react-hooks": reactHooks,
    },
    rules: {
      "react/react-in-jsx-scope": "off",
      "react-hooks/rules-of-hooks": "error",
      "react-hooks/exhaustive-deps": "warn",
    },
    settings: {
      react: { version: "detect" },
    },
  },

  // Custom rules for all files
  {
    rules: {
      "no-unused-vars": "off",
      "@typescript-eslint/no-unused-vars": ["error", {
        argsIgnorePattern: "^_",
        varsIgnorePattern: "^_",
      }],
      "no-console": "warn",
      "prefer-const": "error",
      eqeqeq: ["error", "always"],
    },
  },

  // Ignore patterns
  {
    ignores: ["dist/", "node_modules/", "*.config.js", "coverage/"],
  },
]

Legacy Config (.eslintrc)

{
  "env": {
    "browser": true,
    "es2025": true,
    "node": true
  },
  "extends": [
    "eslint:recommended",
    "plugin:@typescript-eslint/recommended",
    "plugin:react/recommended",
    "plugin:react-hooks/recommended"
  ],
  "parser": "@typescript-eslint/parser",
  "parserOptions": {
    "ecmaVersion": "latest",
    "sourceType": "module",
    "ecmaFeatures": { "jsx": true }
  },
  "plugins": ["@typescript-eslint", "react"],
  "rules": {
    "no-console": "warn",
    "prefer-const": "error",
    "no-unused-vars": "off",
    "@typescript-eslint/no-unused-vars": "error"
  },
  "ignorePatterns": ["dist/", "node_modules/"]
}

Common Rules

Error Prevention

RuleDescription
no-undefDisallow undeclared variables
no-unused-varsDisallow unused variables
no-unreachableDisallow unreachable code
no-dupe-keysDisallow duplicate keys in objects
no-duplicate-caseDisallow duplicate case labels
no-constant-conditionDisallow constant conditions in tests
no-debuggerDisallow debugger statements
use-isnanRequire isNaN() for NaN checks
valid-typeofEnforce valid typeof comparisons

Best Practices

RuleDescription
eqeqeqRequire === and !==
no-evalDisallow eval()
no-implied-evalDisallow implied eval in setTimeout/setInterval
no-varRequire let or const instead of var
prefer-constPrefer const for never-reassigned variables
no-throw-literalRequire throwing Error objects
no-return-awaitDisallow unnecessary return await
curlyRequire curly braces for all control statements

Rule Severity

// "off" or 0 — disable the rule
// "warn" or 1 — warn (does not affect exit code)
// "error" or 2 — error (exit code 1)

rules: {
  "no-console": "warn",        // or 1
  "no-debugger": "error",      // or 2
  "no-alert": "off",           // or 0
  "semi": ["error", "always"], // rule with options
}

Advanced Usage

Inline Directives

/* eslint-disable no-console */
console.log("This line won't trigger a warning")
/* eslint-enable no-console */

// Disable for a single line
console.log("ok") // eslint-disable-line no-console

// Disable for the next line
// eslint-disable-next-line no-console
console.log("ok")

// Disable entire file
/* eslint-disable */

// Disable multiple rules
/* eslint-disable no-console, no-alert */

Custom Rules

// eslint-rules/no-foo.js
module.exports = {
  meta: {
    type: "suggestion",
    docs: { description: "Disallow use of foo" },
    fixable: "code",
    schema: [],
  },
  create(context) {
    return {
      Identifier(node) {
        if (node.name === "foo") {
          context.report({
            node,
            message: "Avoid using 'foo'",
            fix(fixer) {
              return fixer.replaceText(node, "bar")
            },
          })
        }
      },
    }
  },
}

Per-File Configuration

// eslint.config.js
export default [
  // Stricter rules for source code
  {
    files: ["src/**/*.{ts,tsx}"],
    rules: {
      "no-console": "error",
      "@typescript-eslint/explicit-function-return-type": "error",
    },
  },

  // Relaxed rules for tests
  {
    files: ["**/*.test.{ts,tsx}", "**/*.spec.{ts,tsx}"],
    rules: {
      "no-console": "off",
      "@typescript-eslint/no-explicit-any": "off",
    },
  },

  // Config files
  {
    files: ["*.config.{js,ts}"],
    rules: {
      "import/no-default-export": "off",
    },
  },
]

Integration with Prettier

# Install integration packages
npm install -D eslint-config-prettier eslint-plugin-prettier
// eslint.config.js
import prettier from "eslint-config-prettier"

export default [
  // ... your configs
  prettier, // Must be last to override formatting rules
]

CI/CD Integration

# .github/workflows/lint.yml
name: Lint
on: [push, pull_request]
jobs:
  lint:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - uses: actions/setup-node@v4
        with:
          node-version: 20
      - run: npm ci
      - run: npx eslint --max-warnings 0 .

Troubleshooting

IssueSolution
Rules not appliedRun npx eslint --print-config file.js to see resolved config
Flat config not recognizedEnsure ESLint 9+; file must be eslint.config.js (not .eslintrc)
Plugin not foundInstall the plugin package; check import in config file
TypeScript parsing errorsInstall @typescript-eslint/parser; set parserOptions.project for type-aware rules
Slow lintingUse --cache flag; exclude node_modules and build directories
Conflicting with PrettierAdd eslint-config-prettier as the last config entry
Config migration from .eslintrcUse npx @eslint/migrate-config .eslintrc.json for automatic migration
VS Code not showing errorsInstall the ESLint extension; check output panel for errors
Cannot find module errorsRun npm install; check that all plugin packages are in devDependencies