{"post":{"slug":"how-to-set-up-eslint-2026","title":"How to set up ESLint in 2026: flat config, TypeScript, and team rules","excerpt":"ESLint moved to flat config in 2024 and it is now the universal standard. This is the 2026 guide to a fast, effective ESLint setup for TypeScript projects.","category":"code","date":"April 3, 2026","author":"ByteLedger Team","content":"<span class=\"dropcap\">E</span>SLint is the most widely used JavaScript linter in the world, and in 2026 it has settled into a mature, stable toolchain with flat config as the standard, excellent TypeScript support, and tight editor integration. The old `.eslintrc` format is deprecated — if you have not migrated to `eslint.config.js`, now is the time. This guide covers a practical setup from scratch to CI.\n\n## What changed in 2026\n\n- **ESLint 9 made flat config the default and deprecated `.eslintrc`.** Migration is straightforward for most projects; the `@eslint/migrate-config` tool handles 80% of it automatically.\n- **`@typescript-eslint` v8 unified the two packages** (`@typescript-eslint/parser` and `@typescript-eslint/eslint-plugin`) under a single `typescript-eslint` import.\n- **ESLint runs in parallel** with the new worker-based architecture — lint times on large codebases dropped by 30–50%.\n- **Biome emerged as a faster alternative** for teams that want a single tool for linting and formatting, though ESLint still has broader rule coverage.\n\n## Install\n\n```bash\nnpm install --save-dev eslint typescript-eslint\n# For Prettier integration:\nnpm install --save-dev prettier eslint-config-prettier\n```\n\n## Basic flat config (JavaScript)\n\n```javascript\n// eslint.config.js\nimport js from '@eslint/js';\n\nexport default [\n  js.configs.recommended,\n  {\n    rules: {\n      'no-console': 'warn',\n      'no-unused-vars': 'error',\n      'prefer-const': 'error',\n    },\n  },\n];\n```\n\n## TypeScript setup (recommended)\n\n```javascript\n// eslint.config.js\nimport js from '@eslint/js';\nimport tseslint from 'typescript-eslint';\nimport prettier from 'eslint-config-prettier';\n\nexport default tseslint.config(\n  js.configs.recommended,\n  ...tseslint.configs.recommendedTypeChecked,\n  {\n    languageOptions: {\n      parserOptions: {\n        project: true,        // use tsconfig.json\n        tsconfigRootDir: import.meta.dirname,\n      },\n    },\n  },\n  prettier,                   // disable ESLint rules that conflict with Prettier\n  {\n    rules: {\n      '@typescript-eslint/no-floating-promises': 'error',\n      '@typescript-eslint/no-explicit-any': 'warn',\n      '@typescript-eslint/consistent-type-imports': 'error',\n      'no-console': ['warn', { allow: ['warn', 'error'] }],\n    },\n  },\n  {\n    ignores: ['dist/', 'node_modules/', '*.d.ts'],\n  },\n);\n```\n\n## The rules that matter most for TypeScript\n\n| Rule | Why it matters |\n| --- | --- |\n| `@typescript-eslint/no-floating-promises` | Unhandled promises are a common source of silent failures |\n| `@typescript-eslint/no-misused-promises` | Prevents passing async functions where sync ones are expected |\n| `@typescript-eslint/consistent-type-imports` | Enforces `import type` for type-only imports — better tree-shaking |\n| `@typescript-eslint/no-explicit-any` | Keeps the type system honest |\n| `no-unused-vars` (TS version) | Dead code left in after refactoring |\n| `prefer-const` | Forces immutable-by-default declarations |\n\n## Prettier integration (do it right)\n\nRun ESLint and Prettier as separate tools — do not use `eslint-plugin-prettier`:\n\n```json\n// package.json scripts\n{\n  \"scripts\": {\n    \"lint\": \"eslint .\",\n    \"lint:fix\": \"eslint . --fix\",\n    \"format\": \"prettier --write .\",\n    \"format:check\": \"prettier --check .\"\n  }\n}\n```\n\n`eslint-config-prettier` (the last entry in your config) disables the ESLint rules that would conflict with Prettier's formatting decisions. Prettier handles formatting; ESLint handles code quality.\n\n## Per-directory overrides\n\nFlat config makes per-directory rules easy:\n\n```javascript\nexport default tseslint.config(\n  // ... base config ...\n  {\n    files: ['src/**/*.test.ts', 'src/**/*.spec.ts'],\n    rules: {\n      '@typescript-eslint/no-explicit-any': 'off',  // more permissive in tests\n      'no-console': 'off',\n    },\n  },\n  {\n    files: ['scripts/**/*.js'],\n    rules: {\n      'no-console': 'off',  // scripts can log freely\n    },\n  },\n);\n```\n\n## CI integration\n\n```yaml\n# .github/workflows/lint.yml\nname: Lint\non: [push, pull_request]\njobs:\n  lint:\n    runs-on: ubuntu-latest\n    steps:\n      - uses: actions/checkout@v4\n      - uses: actions/setup-node@v4\n        with:\n          node-version: '22'\n          cache: 'npm'\n      - run: npm ci\n      - run: npm run lint\n      - run: npm run format:check\n```\n\n## How to pick your rule set\n\n1. **Greenfield TypeScript project?** Start with `tseslint.configs.recommendedTypeChecked` plus `eslint-config-prettier`. Add rules from `tseslint.configs.strictTypeChecked` as the team's comfort grows.\n2. **Migrating a large JS codebase?** Start with `js.configs.recommended` only, fix violations, then layer in TypeScript rules incrementally.\n3. **React project?** Add `eslint-plugin-react`, `eslint-plugin-react-hooks`, and `eslint-plugin-jsx-a11y`.\n4. **Node.js backend?** Add `eslint-plugin-n` for Node-specific rules (deprecated API detection, import resolution).\n5. **Speed matters above all?** Try Biome as a Rust-based alternative — 10–20× faster, single config for lint and format.\n\n## Common mistakes\n\n**Using `.eslintrc` with ESLint 9+.** The legacy config format requires the compatibility shim (`@eslint/eslintrc`) and will be removed in a future version. Migrate now.\n\n**`no-explicit-any: error` on a legacy codebase.** This will produce hundreds of errors and block adoption. Start with `warn`, fix over time, promote to `error` once clean.\n\n**Not running ESLint in CI.** Editor-only linting means violations reach main whenever someone commits outside the editor or with plugins disabled.\n\n**Linting generated code.** Auto-generated files (`*.d.ts`, codegen output) should be in `ignores` — linting them adds noise and slows runs.\n\n**Different ESLint versions across team members.** Lock ESLint in `devDependencies` and run through `npm ci` in CI, not global installs.\n\n## What to skip\n\n- **`eslint-plugin-prettier`** — it runs Prettier as an ESLint rule, which is slower and conflates two concerns. Use them separately.\n- **Every `@eslint/recommended` rule** without reading what each does — some rules are too strict for your codebase and generate noise that desensitises the team.\n- **Custom rules for style** that Prettier already handles — indent, quotes, semicolons are Prettier's job.\n\n## FAQ\n\n**How do I migrate from `.eslintrc` to flat config?**\nRun `npx @eslint/migrate-config .eslintrc.json`. It generates an `eslint.config.mjs` from your existing config. Review it manually — some plugins have not released flat-config-compatible versions yet.\n\n**Should I use `recommendedTypeChecked` or just `recommended`?**\nUse `recommendedTypeChecked` — it enables rules that require type information (like `no-floating-promises`) and catches a class of bugs that type-unaware rules miss entirely.\n\n**Is Biome ready to replace ESLint?**\nFor most projects, Biome is production-ready and dramatically faster. The gap is plugin ecosystem — ESLint has hundreds of framework-specific plugins that Biome does not yet match. Evaluate based on whether you need those plugins.\n\n**How do I share an ESLint config across multiple packages in a monorepo?**\nCreate a shared `eslint-config-<yourname>` package in your monorepo and reference it from each package's `eslint.config.js`. Flat config makes this simpler than the legacy `extends` approach.\n\n## Where to go next\n\nSee [How to reduce bundle size in 2026](/blog/how-to-reduce-bundle-size-2026), [How to write unit tests in 2026](/blog/how-to-write-unit-tests-2026), and [How to set up CI/CD in 2026](/blog/how-to-set-up-ci-cd-2026).","hue":322,"metaTitle":"How to Set Up ESLint in 2026: Flat Config and TypeScript","metaDescription":"Set up ESLint in 2026 with flat config, TypeScript rules, Prettier integration, and CI enforcement. The practical guide for modern JS/TS projects.","keywords":["how to set up eslint 2026","eslint flat config guide","eslint typescript 2026","eslint 9 configuration","eslint prettier integration 2026","typescript eslint rules","eslint ci integration","eslint rules best practices","eslint config js","javascript linting 2026"],"tldr":["**Use flat config (eslint.config.js)** — the legacy .eslintrc format is deprecated in ESLint 9+ and will be removed.","**Combine ESLint with Prettier via eslint-config-prettier** — do not use eslint-plugin-prettier; run them separately.","**TypeScript-aware rules require @typescript-eslint/eslint-plugin** — plain ESLint does not understand TS types.","**Run ESLint in CI as a required check** — linting only in editors means rule violations ship to production regularly.","**Skip:** enabling every recommended rule blindly — start with a minimal set, add rules when a class of bug actually bites you."],"readTime":"4 min read","wordCount":957},"related":[{"slug":"how-to-set-up-prettier-2026","title":"How to set up Prettier in 2026","excerpt":"Prettier ends code-style debates by enforcing a single format on save. This guide covers installation, config, editor integration, and CI enforcement in 2026.","category":"code","date":"March 16, 2026","author":"ByteLedger Team","readTime":"4 min read","hue":306},{"slug":"biome-vs-eslint-prettier-2026","title":"Biome vs ESLint + Prettier in 2026: when to switch toolchains","excerpt":"Biome has matured into a credible all-in-one alternative to ESLint and Prettier. Here's the honest comparison and the migration playbook for 2026.","category":"code","date":"February 10, 2026","author":"ByteLedger Team","readTime":"3 min read","hue":155},{"slug":"how-to-learn-typescript-2026","title":"How to learn TypeScript in 2026: from JavaScript to typed confidence","excerpt":"TypeScript is now the default language for serious JavaScript projects. Here is the practical 2026 path to learning it without getting lost in complexity.","category":"code","date":"April 1, 2026","author":"ByteLedger Team","readTime":"5 min read","hue":313}],"sameCategory":[{"slug":"bazel-build-explained-2026","title":"Bazel Explained: What Hermetic Builds Actually Cost","excerpt":"Bazel delivers reproducible, precisely cached builds and demands that you describe everything. Here is what you get, what it costs, and who should say no.","category":"code","date":"August 19, 2026","author":"ByteLedger Team","readTime":"3 min read","hue":145},{"slug":"graphql-federation-2026","title":"GraphQL Federation: One Graph, Many Teams","excerpt":"Federation composes independently-owned subgraphs into a single API. Here is what it solves, the operational cost it adds, and when a simpler gateway is enough.","category":"code","date":"August 19, 2026","author":"ByteLedger Team","readTime":"3 min read","hue":300},{"slug":"hermetic-builds-explained-2026","title":"Hermetic Builds Explained: Same Inputs, Same Output","excerpt":"A hermetic build depends only on declared inputs. Here is what that property gives you, the common leaks that break it, and how to move toward it incrementally.","category":"code","date":"August 19, 2026","author":"ByteLedger Team","readTime":"3 min read","hue":130},{"slug":"monorepo-tooling-compared-2026","title":"Monorepo Tooling Compared: What You Actually Need","excerpt":"Monorepo tools solve task orchestration and caching, not repository layout. Here is what each tier provides and how to tell when you have outgrown the simple option.","category":"code","date":"August 19, 2026","author":"ByteLedger Team","readTime":"3 min read","hue":150}],"newer":{"slug":"how-to-set-up-automatic-investing-2026","title":"How to set up automatic investing in 2026: the one move that beats willpower","excerpt":"Automatic investing is the single highest-leverage habit in personal finance. Here is exactly how to set it up in 2026 so it runs without you.","category":"finance","date":"April 3, 2026","author":"ByteLedger Team","readTime":"4 min read","hue":274},"older":{"slug":"how-to-set-up-obs-2026","title":"How to set up OBS in 2026: scenes, encoding, and audio the right way","excerpt":"OBS Studio is still the best free tool for streaming and recording in 2026. Here is how to configure it properly from scratch, including AV1 and audio.","category":"tech","date":"April 3, 2026","author":"ByteLedger Team","readTime":"5 min read","hue":252}}