Eslint Prettier
ESLint and Prettier combined setup for JavaScript and TypeScript linting and formatting
You are an expert in configuring ESLint and Prettier together for consistent code quality and formatting in JavaScript and TypeScript projects. ## Key Points - Use `eslint-config-prettier` to disable all ESLint rules that conflict with Prettier. This must come last in the config array. - Use flat config (`eslint.config.mjs`) for new projects; the legacy `.eslintrc` format is deprecated in ESLint v9. - Enable `projectService` in `parserOptions` for type-aware rules like `no-floating-promises`. These catch real bugs. - Use `lint-staged` with Husky to run linting only on staged files, keeping pre-commit hooks fast. - Prefer `warn` for stylistic rules and `error` for correctness rules to avoid blocking development on non-critical issues. - Use the underscore pattern (`argsIgnorePattern: '^_'`) for intentionally unused function parameters. - **Conflicting formatting rules**: If Prettier and ESLint fight over formatting, ensure `eslint-config-prettier` is the last config applied. It disables conflicting ESLint formatting rules. - **Flat config vs legacy config**: ESLint v9 uses `eslint.config.mjs` by default. Do not mix `.eslintrc.*` files with flat config; only one system is used per project. - **Missing parser for TypeScript**: If you see parsing errors on `.ts` files, ensure `typescript-eslint` is configured. The default ESLint parser does not understand TypeScript syntax. - **Prettier version mismatches in teams**: Pin Prettier version exactly and use `.prettierrc` to ensure identical formatting output across all environments. ## Quick Example ```bash npm install --save-dev eslint @eslint/js typescript-eslint npm install --save-dev prettier eslint-config-prettier eslint-plugin-prettier npm install --save-dev globals ``` ``` dist node_modules coverage pnpm-lock.yaml ```
skilldb get build-tools-skills/Eslint PrettierFull skill: 219 linesESLint + Prettier — Build Tools
You are an expert in configuring ESLint and Prettier together for consistent code quality and formatting in JavaScript and TypeScript projects.
Core Philosophy
Overview
ESLint is the standard JavaScript/TypeScript linter for catching bugs and enforcing code patterns. Prettier is an opinionated code formatter. Used together, ESLint handles code quality rules while Prettier handles formatting. ESLint v9 introduced flat config (eslint.config.mjs) which replaces the legacy .eslintrc format.
Setup & Configuration
Installation (ESLint v9 + Prettier)
npm install --save-dev eslint @eslint/js typescript-eslint
npm install --save-dev prettier eslint-config-prettier eslint-plugin-prettier
npm install --save-dev globals
eslint.config.mjs (Flat Config)
import js from '@eslint/js';
import tseslint from 'typescript-eslint';
import prettierConfig from 'eslint-config-prettier';
import prettierPlugin from 'eslint-plugin-prettier';
import globals from 'globals';
export default tseslint.config(
js.configs.recommended,
...tseslint.configs.recommended,
prettierConfig,
{
plugins: {
prettier: prettierPlugin,
},
rules: {
'prettier/prettier': 'warn',
'@typescript-eslint/no-unused-vars': [
'error',
{ argsIgnorePattern: '^_', varsIgnorePattern: '^_' },
],
'@typescript-eslint/no-explicit-any': 'warn',
'@typescript-eslint/consistent-type-imports': 'error',
'no-console': ['warn', { allow: ['warn', 'error'] }],
},
languageOptions: {
globals: {
...globals.browser,
...globals.node,
},
parserOptions: {
projectService: true,
tsconfigRootDir: import.meta.dirname,
},
},
},
{
files: ['**/*.test.ts', '**/*.spec.ts'],
rules: {
'@typescript-eslint/no-explicit-any': 'off',
'no-console': 'off',
},
},
{
ignores: ['dist/', 'node_modules/', 'coverage/', '*.gen.ts'],
}
);
.prettierrc
{
"semi": true,
"singleQuote": true,
"trailingComma": "all",
"printWidth": 100,
"tabWidth": 2,
"endOfLine": "lf",
"bracketSpacing": true,
"arrowParens": "always"
}
.prettierignore
dist
node_modules
coverage
pnpm-lock.yaml
package.json Scripts
{
"scripts": {
"lint": "eslint .",
"lint:fix": "eslint . --fix",
"format": "prettier --write .",
"format:check": "prettier --check .",
"check": "eslint . && prettier --check ."
}
}
Core Patterns
React Project Additions
npm install --save-dev eslint-plugin-react eslint-plugin-react-hooks
import react from 'eslint-plugin-react';
import reactHooks from 'eslint-plugin-react-hooks';
// Add to config array:
{
plugins: {
react,
'react-hooks': reactHooks,
},
rules: {
...reactHooks.configs.recommended.rules,
'react/react-in-jsx-scope': 'off',
'react/prop-types': 'off',
},
settings: {
react: { version: 'detect' },
},
}
Type-Aware Rules
// In the config object with parserOptions.projectService:
{
rules: {
'@typescript-eslint/no-floating-promises': 'error',
'@typescript-eslint/no-misused-promises': 'error',
'@typescript-eslint/await-thenable': 'error',
'@typescript-eslint/require-await': 'error',
},
}
Lint-Staged + Husky
npm install --save-dev husky lint-staged
npx husky init
// package.json
{
"lint-staged": {
"*.{ts,tsx,js,jsx}": ["eslint --fix", "prettier --write"],
"*.{json,md,css}": ["prettier --write"]
}
}
# .husky/pre-commit
npx lint-staged
Inline Directives
// eslint-disable-next-line @typescript-eslint/no-explicit-any
const data: any = legacy.getValue();
/* eslint-disable no-console */
console.log('Debug block');
console.log('More debug');
/* eslint-enable no-console */
Best Practices
- Use
eslint-config-prettierto disable all ESLint rules that conflict with Prettier. This must come last in the config array. - Use flat config (
eslint.config.mjs) for new projects; the legacy.eslintrcformat is deprecated in ESLint v9. - Enable
projectServiceinparserOptionsfor type-aware rules likeno-floating-promises. These catch real bugs. - Use
lint-stagedwith Husky to run linting only on staged files, keeping pre-commit hooks fast. - Prefer
warnfor stylistic rules anderrorfor correctness rules to avoid blocking development on non-critical issues. - Use the underscore pattern (
argsIgnorePattern: '^_') for intentionally unused function parameters.
Common Pitfalls
- Conflicting formatting rules: If Prettier and ESLint fight over formatting, ensure
eslint-config-prettieris the last config applied. It disables conflicting ESLint formatting rules. - Flat config vs legacy config: ESLint v9 uses
eslint.config.mjsby default. Do not mix.eslintrc.*files with flat config; only one system is used per project. - Type-aware rules are slow: Rules using
projectServiceorprojectparse your TypeScript project, which adds startup time. This is normal. Use them in CI and lint-staged, not on every keystroke if it feels slow. - Missing parser for TypeScript: If you see parsing errors on
.tsfiles, ensuretypescript-eslintis configured. The default ESLint parser does not understand TypeScript syntax. - Prettier version mismatches in teams: Pin Prettier version exactly and use
.prettierrcto ensure identical formatting output across all environments.
Anti-Patterns
Over-engineering for hypothetical scale. Building for millions of users when you have hundreds adds complexity without value. Solve today's problems first.
Ignoring the existing ecosystem. Reinventing functionality that mature libraries already provide well wastes time and introduces unnecessary risk.
Premature abstraction. Creating elaborate frameworks and utilities before you have enough concrete cases to know what the abstraction should look like produces the wrong abstraction.
Neglecting error handling at boundaries. Internal code can trust its inputs, but system boundaries (user input, APIs, file I/O) require defensive validation.
Skipping documentation for obvious code. What is obvious to you today will not be obvious to your colleague next month or to you next year.
Install this skill directly: skilldb add build-tools-skills
Related Skills
Biome
Biome linter, formatter, and code analysis configuration for JavaScript and TypeScript projects
Esbuild
esbuild bundling, transpilation, and build scripting for ultra-fast JavaScript builds
Rollup
Rollup configuration for building JavaScript libraries with tree shaking and multiple output formats
Swc
SWC compiler configuration for fast TypeScript and JavaScript transpilation and minification
Tsconfig
TypeScript compiler configuration, project references, and tsconfig best practices
Vite
Vite configuration, plugins, and dev server optimization for modern JavaScript projects