ESLint Cheatsheet
Pluggable linting for JavaScript and TypeScript.
Contents
- •Setup
- •Running ESLint
- •Configuration Presets
- •Common Plugins
- •Rule Configuration
- •File-Specific Configuration
- •Ignoring Files
- •Migration from Legacy Config
- •CI Integration
Setup
Install (Flat Config - ESLint 9+)
bash
bun add -D eslint @eslint/js typescript-eslint globals
eslint.config.js (Recommended)
javascript
import js from "@eslint/js";
import tseslint from "typescript-eslint";
import globals from "globals";
export default tseslint.config(
js.configs.recommended,
...tseslint.configs.recommended,
{
languageOptions: {
globals: {
...globals.node,
...globals.es2022,
},
},
},
{
ignores: ["dist/", "node_modules/", "*.config.js"],
}
);
eslint.config.js (Strict TypeScript)
javascript
import js from "@eslint/js";
import tseslint from "typescript-eslint";
import globals from "globals";
export default tseslint.config(
js.configs.recommended,
...tseslint.configs.strictTypeChecked,
...tseslint.configs.stylisticTypeChecked,
{
languageOptions: {
globals: {
...globals.node,
...globals.es2022,
},
parserOptions: {
projectService: true,
tsconfigRootDir: import.meta.dirname,
},
},
},
{
ignores: ["dist/", "node_modules/"],
}
);
package.json Scripts
json
{
"scripts": {
"lint": "eslint .",
"lint:fix": "eslint . --fix"
}
}
Running ESLint
bash
eslint . # Lint all files eslint src/ # Lint specific directory eslint file.ts # Lint single file eslint . --fix # Auto-fix issues eslint . --fix-dry-run # Preview fixes without applying eslint . --max-warnings 0 # Fail on warnings eslint . --cache # Use cache for faster runs eslint . --format stylish # Output format (stylish, json, compact) eslint . --quiet # Report errors only eslint . --debug # Debug configuration eslint --print-config file.ts # Show config for a file eslint --inspect-config # Open config inspector in browser
Configuration Presets
JavaScript Only
javascript
import js from "@eslint/js";
import globals from "globals";
export default [
js.configs.recommended,
{
languageOptions: {
globals: { ...globals.node },
},
},
];
TypeScript Recommended
javascript
import js from "@eslint/js"; import tseslint from "typescript-eslint"; export default tseslint.config( js.configs.recommended, ...tseslint.configs.recommended, );
TypeScript Strict (Type-Checked)
javascript
import js from "@eslint/js";
import tseslint from "typescript-eslint";
export default tseslint.config(
js.configs.recommended,
...tseslint.configs.strictTypeChecked,
{
languageOptions: {
parserOptions: {
projectService: true,
tsconfigRootDir: import.meta.dirname,
},
},
},
);
Common Plugins
Install Popular Plugins
bash
# React bun add -D eslint-plugin-react eslint-plugin-react-hooks # Import sorting bun add -D eslint-plugin-import # Prettier integration bun add -D eslint-config-prettier eslint-plugin-prettier # Security bun add -D eslint-plugin-security # Node.js bun add -D eslint-plugin-n # JSDoc bun add -D eslint-plugin-jsdoc
React Configuration
javascript
import js from "@eslint/js";
import tseslint from "typescript-eslint";
import react from "eslint-plugin-react";
import reactHooks from "eslint-plugin-react-hooks";
import globals from "globals";
export default tseslint.config(
js.configs.recommended,
...tseslint.configs.recommended,
{
plugins: {
react,
"react-hooks": reactHooks,
},
languageOptions: {
globals: { ...globals.browser },
parserOptions: {
ecmaFeatures: { jsx: true },
},
},
settings: {
react: { version: "detect" },
},
rules: {
...react.configs.recommended.rules,
...reactHooks.configs.recommended.rules,
"react/react-in-jsx-scope": "off",
},
},
);
Prettier Integration
javascript
import js from "@eslint/js"; import tseslint from "typescript-eslint"; import prettier from "eslint-config-prettier"; export default tseslint.config( js.configs.recommended, ...tseslint.configs.recommended, prettier, // Must be last to disable conflicting rules );
Rule Configuration
Rule Severity
javascript
{
rules: {
"no-unused-vars": "off", // 0 - disable
"no-console": "warn", // 1 - warning
"no-debugger": "error", // 2 - error
}
}
Rule with Options
javascript
{
rules: {
"@typescript-eslint/no-unused-vars": ["error", {
argsIgnorePattern: "^_",
varsIgnorePattern: "^_",
}],
"no-restricted-imports": ["error", {
patterns: ["../../../*"],
}],
}
}
Essential Rules
TypeScript Recommended Rules
javascript
{
rules: {
// Prevent unused variables
"@typescript-eslint/no-unused-vars": ["error", {
argsIgnorePattern: "^_",
varsIgnorePattern: "^_",
}],
// Prevent explicit any
"@typescript-eslint/no-explicit-any": "warn",
// Require return types on functions
"@typescript-eslint/explicit-function-return-type": "off",
// Require explicit accessibility modifiers
"@typescript-eslint/explicit-member-accessibility": "off",
// Prevent empty functions
"@typescript-eslint/no-empty-function": "warn",
// Prefer nullish coalescing
"@typescript-eslint/prefer-nullish-coalescing": "warn",
// Prefer optional chaining
"@typescript-eslint/prefer-optional-chain": "warn",
}
}
Code Quality Rules
javascript
{
rules: {
"no-console": "warn",
"no-debugger": "error",
"no-duplicate-imports": "error",
"no-template-curly-in-string": "warn",
"prefer-const": "error",
"prefer-template": "warn",
"eqeqeq": ["error", "always"],
"curly": ["error", "all"],
}
}
File-Specific Configuration
javascript
import js from "@eslint/js";
import tseslint from "typescript-eslint";
import globals from "globals";
export default tseslint.config(
js.configs.recommended,
...tseslint.configs.recommended,
// TypeScript files
{
files: ["**/*.ts", "**/*.tsx"],
rules: {
"@typescript-eslint/explicit-function-return-type": "warn",
},
},
// Test files
{
files: ["**/*.test.ts", "**/*.spec.ts"],
languageOptions: {
globals: { ...globals.jest },
},
rules: {
"@typescript-eslint/no-explicit-any": "off",
},
},
// Config files
{
files: ["*.config.js", "*.config.ts"],
rules: {
"no-console": "off",
},
},
);
Ignoring Files
In Config
javascript
export default [
{
ignores: [
"dist/",
"build/",
"node_modules/",
"*.min.js",
"coverage/",
".next/",
],
},
// ... other configs
];
Inline Disable
javascript
// eslint-disable-next-line no-console
console.log("debug");
/* eslint-disable @typescript-eslint/no-explicit-any */
const data: any = {};
/* eslint-enable @typescript-eslint/no-explicit-any */
// eslint-disable-next-line -- explanation why
Migration from Legacy Config
From .eslintrc to eslint.config.js
bash
# Use migration tool npx @eslint/migrate-config .eslintrc.json
Key Differences
| Legacy (.eslintrc) | Flat Config (eslint.config.js) |
|---|---|
extends | Import and spread configs |
plugins | Object with plugin imports |
env | languageOptions.globals |
parser | languageOptions.parser |
parserOptions | languageOptions.parserOptions |
.eslintignore | ignores array in config |
CI Integration
GitHub Actions
yaml
- name: Lint
run: |
bun install
bun run lint
Pre-commit Hook (with Husky)
bash
bun add -D husky lint-staged npx husky init echo "bunx lint-staged" > .husky/pre-commit
json
{
"lint-staged": {
"*.{js,ts,tsx}": ["eslint --fix", "prettier --write"]
}
}
Debugging
bash
# Check which config applies to a file eslint --print-config src/index.ts # Debug rule resolution eslint --debug src/index.ts # Interactive config inspector eslint --inspect-config # Check installed plugins eslint --env-info
Tips
- •Always use flat config (eslint.config.js) for ESLint 9+
- •Put
prettierconfig last to disable conflicting rules - •Use
--cachein CI for faster runs - •Prefer recommended presets over manual rule configuration
- •Use
typescript-eslinthelper for TypeScript projects - •Run
--fixto auto-fix many issues - •Use
--max-warnings 0to treat warnings as errors in CI - •Enable type-checked rules for stricter TypeScript linting