Ah, ESLint. The unsung hero standing between your codebase and complete anarchy. And yet, some developers still treat it like an oppressive overlord rather than the lifeline it actually is.
If you’ve ever had to wade through a swamp of inconsistent formatting, wildcard imports, and the occasional var
(because some people just want to watch the world burn), this guide is for you. Let’s settle this once and for all: ESLint is not optional.
Why Bother With ESLint? (Aka: Why Do You Hate Yourself?)
Look, I get it. Some of you see code as art, a beautiful, free-flowing expression of logic and creativity. That’s adorable. But guess what? You’re not the only one maintaining it.
Here’s what happens when you don’t use ESLint:
- Your pull requests turn into petty wars over semicolons and indentation.
- Your codebase resembles a Jackson Pollock painting—if he painted with spaghetti.
- Tabs and spaces become indistinguishable, and chaos reigns.
- Debugging turns into archaeology, except instead of uncovering history, you uncover suffering.
And no, TypeScript’s type system isn’t a replacement for ESLint. It won’t stop you from writing unreadable garbage—it will just type-check your unreadable garbage.
Installing ESLint: Because Apparently, This Isn’t Obvious
Step 1: Install It
Yes, really.
For JavaScript:
npm install eslint --save-dev
npx eslint --init
For TypeScript (because everything TypeScript-related requires extra steps):
npm install eslint @typescript-eslint/parser @typescript-eslint/eslint-plugin --save-dev
Step 2: Configure It
When running npx eslint --init
, you’ll answer some questions. Choose wisely—or just use a preset because nobody has time for existential crises over linting rules.
For TypeScript, your .eslintrc.json
should look something like this:
{
"parser": "@typescript-eslint/parser",
"extends": ["plugin:@typescript-eslint/recommended"]
}
Congrats! You now have ESLint. But don’t get comfortable—there’s still plenty of nonsense to fix.
Popular ESLint Rule Sets: Because Smarter People Did the Work for You
- Airbnb — The rule set for those who enjoy being micromanaged.
- Google — Because if it’s good enough for Silicon Valley overlords, it’s good enough for you.
- StandardJS — For people who like strict rules but hate semicolons.
- Meta (Facebook) — For React developers who don’t like admitting they actually enjoy React.
-
TypeScript-Specific — If you’re using TypeScript, just extend
plugin:@typescript-eslint/recommended
and move on.
Example ESLint config using Airbnb’s style guide:
{
"extends": ["airbnb", "plugin:@typescript-eslint/recommended"]
}
Tweaking ESLint Rules: Because Your Team Has ‘Special’ Needs
ESLint comes packed with a massive set of rules—over 500 of them—designed to enforce coding standards, eliminate potential bugs, and make sure your code doesn’t look like a deranged monkey wrote it.
Managing ESLint Rules
Example of tweaking rules in your ESLint config:
{
"rules": {
"no-console": "warn",
"eqeqeq": ["error", "always"],
"complexity": ["warn", { "max": 10 }],
"camelcase": ["error", { "properties": "always" }]
}
}
TypeScript-Specific Rules
Example TypeScript rule configurations:
{
"rules": {
"@typescript-eslint/no-explicit-any": "error",
"@typescript-eslint/naming-convention": [
"error",
{ "selector": "variable", "format": ["camelCase"] }
]
}
}
Disabling Rules Inline
console.log("Debugging"); // eslint-disable-line no-console
Or, disable a rule for a specific block:
/* eslint-disable no-console */
console.log("Debugging");
console.log("More debugging");
/* eslint-enable no-console */
Overriding Rules Per File
{
"overrides": [
{
"files": ["**/*.test.js"],
"rules": {
"no-unused-expressions": "off"
}
}
]
}
Plugins and Extending ESLint Further
To use a plugin, install it via npm and extend it in your .eslintrc
:
npm install eslint-plugin-react --save-dev
{
"extends": ["plugin:react/recommended"]
}
Automating ESLint Fixes
npx eslint . --fix
Creating a Custom ESLint Rule
module.exports = {
meta: {
type: "problem",
docs: {
description: "Ensure all 'await' expressions are wrapped in try/catch",
category: "Best Practices",
recommended: false,
},
messages: {
unguardedAwait: "Unprotected 'await' detected. Wrap it in a try/catch to handle errors properly.",
},
},
create(context) {
return {
AwaitExpression(node) {
let parent = node.parent;
while (parent) {
if (parent.type === "TryStatement") {
return;
}
parent = parent.parent;
}
context.report({ node, messageId: "unguardedAwait" });
},
};
},
};
To enable it in .eslintrc.js
:
module.exports = {
rules: {
"no-unguarded-await": "error",
},
};
The Final Word: Lint or Suffer
Either use ESLint, or prepare to spend your life debugging a codebase that looks like it was written by a caffeine-fueled raccoon. Your choice.
About me site: https://danduh.me/
Follow me on
Top comments (0)