No. 003 · code-quality
ESLint Configuration
Linting rules that catch bugs without fighting your style
Most ESLint pain comes from fighting the default config instead of tuning it. This skill helps you set up a config that catches real bugs while staying out of the way on style choices that don’t matter.
Flat config (eslint.config.mjs)
New projects should use the flat config format. The old .eslintrc is
legacy as of ESLint v9.
// eslint.config.mjs
import js from '@eslint/js';
import tseslint from 'typescript-eslint';
export default tseslint.config(
js.configs.recommended,
...tseslint.configs.recommended,
{
rules: {
'no-unused-vars': 'off',
'@typescript-eslint/no-unused-vars': ['error', {
argsIgnorePattern: '^_',
varsIgnorePattern: '^_',
}],
'@typescript-eslint/no-explicit-any': 'warn',
'no-console': ['warn', { allow: ['warn', 'error'] }],
},
},
{
ignores: ['dist/', 'node_modules/', '*.config.*'],
},
);
Rule tuning principles
Promote to error only rules that catch real bugs:
no-floating-promises— unhandled promises cause silent failuresno-misused-promises— async functions in wrong contextseqeqeq—==coerces in surprising ways
Use warn for code smell that might be intentional:
no-console— sometimes you genuinely want console output@typescript-eslint/no-explicit-any— sometimesanyis the right call
Turn off rules that conflict with your formatter:
- All formatting rules (indentation, semicolons, trailing commas) — let Prettier handle these
no-multiple空格— Prettier manages whitespace
Prettier integration
Install eslint-config-prettier to disable all ESLint rules that
conflict with Prettier:
npm install -D eslint-config-prettier
Then add it as the last config in your flat config array:
import prettier from 'eslint-config-prettier';
export default tseslint.config(
// ... other configs
prettier, // must be last
);
Never use eslint-plugin-prettier (running Prettier through ESLint)
— it’s slow and produces noisy diffs. Run Prettier separately.
Adding custom rules
For project-specific patterns, create a local rule only if no existing rule covers the case. Most needs are met by combining existing rules:
rules: {
// Enforce error handling on specific functions
'@typescript-eslint/no-misused-promises': ['error', {
checksVoidReturn: { attributes: false },
}],
}
See references/flat-config-migration.md for migrating from .eslintrc.
When it triggers
- setting up a new project's linter
- ESLint rule is too strict or too lenient
- conflict between ESLint and Prettier
- migrating from .eslintrc to flat config