ESLint & Prettier Cheat Sheet
Covers ESLint flat config, Prettier formatting options, integrating the two tools without conflicts, and common linting commands.
ESLint Flat Config
Configuring rules with ESLint 9's flat config format.
// eslint.config.jsimport js from '@eslint/js';export default [ js.configs.recommended, { rules: { 'no-unused-vars': 'warn', 'eqeqeq': 'error', // require === / !== over == / != 'no-console': 'off', }, languageOptions: { ecmaVersion: 2022, sourceType: 'module', }, },];
Prettier Configuration
Formatting rules and ignored paths.
{ "semi": true, "singleQuote": true, "trailingComma": "es5", "printWidth": 80, "tabWidth": 2}
Combining ESLint + Prettier
Preventing the two tools from fighting over formatting.
# npm install -D eslint prettier eslint-config-prettierpackage.json Scripts
Common lint and format script entries.
{ "scripts": { "lint": "eslint . --fix", "format": "prettier --write ." }}
Common Rules & CLI
Frequently used flags and packages.
- eslint --fix- auto-fixes any lint violations that have a known fix
- eslint --init- interactive wizard to scaffold a starting configuration
- no-undef- flags use of undeclared variables
- eslint-plugin-react-hooks- enforces the Rules of Hooks in React components
- prettier --check .- verifies formatting without writing changes, ideal for CI
- eslint-config-prettier- disables ESLint stylistic rules that would conflict with Prettier
Type-Aware Linting with typescript-eslint
Rules that need the TypeScript type checker, not just syntax.
// eslint.config.jsimport tseslint from 'typescript-eslint';export default tseslint.config( ...tseslint.configs.strictTypeChecked, { languageOptions: { parserOptions: { project: true, // uses nearest tsconfig.json tsconfigRootDir: import.meta.dirname, }, }, rules: { '@typescript-eslint/no-floating-promises': 'error', '@typescript-eslint/no-unnecessary-condition': 'warn', }, });
Per-Directory Overrides in Flat Config
Scoping different rule sets to test files, scripts, and app code.
// eslint.config.jsexport default [ { ignores: ['dist/**', 'coverage/**', '**/*.generated.ts'] }, { files: ['**/*.test.{js,ts}'], rules: { 'no-console': 'off' }, languageOptions: { globals: { describe: 'readonly', it: 'readonly' } }, }, { files: ['scripts/**/*.js'], rules: { 'no-process-exit': 'off' }, },];
Pre-Commit Enforcement with Husky + lint-staged
Running lint/format only on staged files before each commit.
// package.json{ "scripts": { "prepare": "husky" }, "lint-staged": { "*.{js,ts,tsx}": ["eslint --fix", "prettier --write"], "*.{json,md,css}": ["prettier --write"] }}// .husky/pre-commitnpx lint-staged
Writing a Custom ESLint Rule
A minimal rule that flags a project-specific anti-pattern.
// eslint-local-rules/no-direct-fetch.jsmodule.exports = { meta: { type: 'problem', schema: [] }, create(context) { return { // Selector syntax: any CallExpression whose callee is `fetch` "CallExpression[callee.name='fetch']"(node) { context.report({ node, message: 'Use the shared apiClient wrapper instead of raw fetch().', }); }, }; },};
Advanced Concepts
Terms that come up once a project outgrows the default config.
- no-restricted-imports- blocks specific import paths/patterns, e.g. banning deep imports into a package's internals
- eslint-disable-next-line- scoped inline suppression for one line; prefer this with a comment reason over disabling a rule project-wide
- shareable config- an npm package (e.g. eslint-config-airbnb) exporting a reusable rule set that other projects extend
- rule severity levels- 'off' (0), 'warn' (1), 'error' (2); CI usually treats warnings as non-blocking, errors as failing
- prettier-plugin-*- extends Prettier's formatting to non-JS syntaxes it doesn't natively parse, e.g. Tailwind class sorting
- .prettierignore- excludes generated/vendored files from formatting, separate from ESLint's ignores array
- FlatCompat- adapter from @eslint/eslintrc that lets flat config load legacy .eslintrc-style shareable configs
Let ESLint own code-quality rules (unused vars, hooks rules) and Prettier own formatting: apply eslint-config-prettier last in your config to disable ESLint's formatting rules instead of trying to make both tools agree on style.