Flat Config and Type-Aware Rules
Flat Config and Type-Aware Rules
ESLint 9 defaults to eslint.config.js, an array of flat objects; typescript-eslint composes them:
import tseslint from "typescript-eslint";
export default tseslint.config(
{ ignores: ["dist", "coverage"] },
...tseslint.configs.recommendedTypeChecked,
{
languageOptions: {
parserOptions: { projectService: true, tsconfigRootDir: import.meta.dirname },
},
rules: { "@typescript-eslint/no-unsafe-argument": "error" },
},
);
Type-aware rules read the real type graph, which is how no-floating-promises catches an unawaited promise and no-unsafe-argument flags any flowing into a typed parameter — checks a syntax-only parser cannot make.
Prettier Without Friction
Prettier Without Friction
ESLint finds problems; Prettier formats. Running both on style rules causes flip-flop diffs, so the integration is a conflict disabler:
import prettier from "eslint-config-prettier";
export default tseslint.config(
...tseslint.configs.recommended,
prettier, // last: turns off formatting rules Prettier owns
);
eslint-config-prettier only switches conflicting rules off. The older eslint-plugin-prettier approach — running Prettier inside ESLint as a rule — reports formatting as lint errors and doubles run time; prefer prettier --write as its own script, with an editor formatter on save so both tools see the same code.
Pitfalls and Interview Angles
Pitfalls and Interview Angles
Speed. Type-aware linting builds a program per project; projectService reuses TypeScript's own service instead of per-run project globs, and ignoring dist keeps work bounded. Splitting a monorepo into per-package configs lets CI lint changed packages only.
Disabling rules. Prefer targeted eslint-disable-next-line with a reason over config-wide off; blanket disables hide the exact bugs the rules exist to catch.
Drift. Same ESLint version, same config, same files in editor and CI — pin the version and run eslint . rather than IDE-on-save only.
Interview: explain what type-aware linting trades (time, a valid tsconfig) for capability (promise and unsafe-any rules), and where it must sit in a pipeline.
Quiz
1. What does eslint-config-prettier actually change?
2. Which rule requires type information to work?
3. Why put prettier last in the flat config array?
Flashcards
Question
Flat config
Click to reveal answer
Answer
ESLint 9's eslint.config.js array of objects; later entries override earlier rules.
Question
Type-aware linting
Click to reveal answer
Answer
Rules that query the TS type graph — enables no-floating-promises and no-unsafe-argument.
Question
projectService
Click to reveal answer
Answer
typescript-eslint option reusing TypeScript's project service so config and speed improve.
Question
eslint-config-prettier
Click to reveal answer
Answer
Disables conflicting stylistic rules; it does not format anything itself.
Revision Notes
Key Takeaways
- 1. Type-aware rules are the reason to run ESLint on TypeScript at all
- 2. Let Prettier own formatting; ESLint owns correctness
- 3. Pin versions and run the same command in editor and CI
Interview Tips
- • Name a bug only type-aware linting catches, and explain the cost it adds
- • Defend why eslint-plugin-prettier-as-a-rule was abandoned in practice
Cheat Sheet
ESLint 9 flat config + tseslint recommendedTypeChecked, projectService:true; eslint-config-prettier last; prettier --write separately; lint dist ignored.