July 27, 2026

JavaScript Formatter vs ESLint: Why Clean Code Is Not Always Correct Code


Paste a messy script into a formatter, get back something clean and neatly indented, and it is easy to assume the job is done. Then ESLint runs and flags a dozen issues you never would have guessed were there, an unused variable here, a comparison that should use strict equality there. This mix-up happens constantly, and it comes from a reasonable assumption: that clean-looking code and correct code are the same thing. They are not, and understanding why is the whole point of this article.

A JavaScript formatter and ESLint get lumped together because they both touch the same files and both sound like quality-control tools. In practice they check completely different things, and knowing which one is actually responsible for a given problem saves you from chasing the wrong fix.

The confusion is not really anyone’s fault. Both tools live in the same mental bucket, "things that clean up my code," and both are commonly configured to run automatically inside the same editor. It is only once you actually need one and reach for the other that the difference becomes obvious.

What a JavaScript Formatter Actually Checks

A formatter looks at spacing. That is really the whole job. It takes your JavaScript, figures out how deeply each block is nested, and rebuilds the file with consistent indentation and line breaks so the structure is visible at a glance.

It does not ask whether that code is well-written. If you hand it a script with an unused variable or a sloppy comparison, it will format the script exactly as written, unused variable and all. The output looks orderly, which is exactly what makes this tool easy to mistake for something it was never designed to be.

What ESLint Actually Checks

ESLint is a linter, a tool that analyzes your JavaScript for potential bugs, questionable patterns, and style rule violations that go well beyond indentation. It is looking for things like variables that are declared but never used, comparisons using == where === would avoid unexpected type coercion, unreachable code after a return statement, and dozens of other configurable rules most developers have not memorized and were never expected to.

This is a fundamentally different kind of check. ESLint does not care how your file is indented, that is not its job. It cares whether the code itself follows sensible patterns and avoids the kinds of mistakes that tend to cause real bugs.

This distinction matters more than it sounds like it should, because JavaScript itself is remarkably forgiving. The engine will happily execute code with an unused variable, a risky comparison, or a confusing pattern without any visible complaint. That forgiveness is convenient day to day, but it also means genuinely risky patterns can sit in a codebase indefinitely without anyone noticing, simply because nothing ever visibly broke.

The Example That Makes This Click

Take this snippet:

function getDiscount(price) {
  let discount = 0;
  if (price == "100") {
    discount = 10;
  }
  return price - discount;
}
Run it through a formatter and you get back the exact same logic, just with clean, consistent indentation. Nothing about the code itself changes. The formatter has no reason to flag the == comparison, since indentation looks perfectly fine either way.

ESLint, on the other hand, would very likely flag that comparison, since comparing a number to a string with loose equality can produce surprising results depending on the values involved. It would also be worth noticing that discount is declared with let but never reassigned, which many ESLint configurations flag as a candidate for const instead. Neither of these issues is a formatting problem. Both are exactly what a linter exists to catch.

Side-by-Side: Formatter vs ESLint

Aspect JavaScript Formatter ESLint
Primary job Improve readability through indentation and spacing Catch potential bugs and enforce code quality rules
Detects unused variables No Yes
Detects risky comparisons No Yes
Changes how the code runs No No, but flags issues that might affect behavior
Typical use moment While actively writing or cleaning up code Continuously, often on save or before commit

When You Actually Need Each One

Reach for a formatter when a file is technically fine but hard to read, minified code, something pasted from another source, or a project where indentation has drifted into inconsistency. This is the more frequent, everyday need, and it is purely about readability.

Reach for ESLint continuously, ideally configured to run automatically as you write code rather than as a separate manual step. Unlike formatting, which you might only need occasionally, linting catches the kind of subtle logic issues that are genuinely easy to introduce without noticing, an unused import, a variable that shadows another, a condition that can never actually be true. These are exactly the class of problem that a quick visual scan will not reliably catch.

There is also a middle-ground case worth mentioning: inheriting a large, unfamiliar codebase. Running ESLint across the whole thing early on can surface risky patterns you would otherwise only discover one at a time, months apart, whenever each one happens to cause a visible symptom.

A Walkthrough: Catching a Bug Neither Tool Catches Alone

Imagine a developer inherits a function that occasionally returns the wrong result under specific conditions. The instinct is to add console logs and step through the logic manually, which eats up most of an afternoon with no clear answer.

Eventually, they paste the function into a formatter, mostly just to make it easier to read while debugging. The formatted output does not fix anything directly, but with the structure now clear, ESLint flags a loose equality comparison buried inside a nested conditional, one that was silently coercing a string to a number in a way nobody had intended. The formatter made the code visible enough to actually look at it closely. ESLint named the exact issue once someone did.

This is really the argument for using both tools rather than picking a favorite. A formatter makes problems visible. ESLint names them directly.

Common Misunderstandings

A surprising number of developers assume that if their formatter did not complain, their code must be fine. It is an understandable assumption, since a formatter is often the only tool people reach for day to day, but it is not what the tool was built to check.

The reverse mistake happens too, less often. Someone runs ESLint for the first time on an older project, sees dozens of warnings, and assumes the codebase is riddled with bugs, when in reality many of those warnings are style preferences, like requiring single quotes over double quotes, that have nothing to do with actual correctness. ESLint output takes some judgment to interpret, and most teams tune the rule set to match what they actually care about rather than accepting every default rule at full severity.

A third, quieter misunderstanding is assuming a clean ESLint run means the code is bug-free. ESLint catches known, definable patterns, it cannot reason about business logic or catch a bug that does not correspond to any rule in its configuration. A file can pass every lint check and still contain a genuine mistake that only shows up under specific real-world conditions.

Why ESLint and Prettier Are Usually Used Together

In the JavaScript ecosystem, Prettier typically handles formatting while ESLint handles code quality, and the two are commonly configured to work side by side without stepping on each other. Since both tools can technically flag spacing-related issues, most setups explicitly turn off ESLint’s own formatting rules and let Prettier own that responsibility entirely, while ESLint focuses purely on logic and code quality concerns.

This division keeps the tools from disagreeing with each other, which used to be a common source of frustration before this pattern became standard. Prettier reformats a file on save, and ESLint runs alongside it, or as a separate step before a commit, checking for the kinds of issues formatting alone was never meant to catch.

This separation of concerns is worth keeping in mind even outside a fully configured project. If you are ever unsure whether a particular complaint is a formatting issue or a code quality issue, ask what it is actually checking, whitespace and indentation point to a formatter’s territory, while anything about variable usage, comparisons, or logic patterns points squarely to a linter’s job.

Using Both Together Without It Feeling Like Extra Work

In practice, most developers do not think of this as two separate manual steps every single time. Formatting tends to run constantly, often automatically through an editor extension, simply because readable code is useful all the time. ESLint often runs the same way, directly inside the editor, underlining problems in real time as you type, rather than as something you have to remember to trigger.

For a quick one-off check outside a full project setup, running your code through ToolMato’s JavaScript Formatter first, to make the structure easy to read, is a reasonable starting point before digging into any logic issues by eye or with a linter.

Best Practices for Using Formatters and ESLint Together

  • Format code regularly, as part of your normal writing process, not as a special occasion.
  • Configure ESLint to run continuously in your editor rather than treating it as a separate manual check.
  • Do not assume clean formatting means correct code. They are unrelated checks that happen to look similar on the surface.
  • Tune your ESLint rule set to match what your team actually cares about, rather than accepting every default rule at full severity.
  • When debugging an issue you cannot explain, format the file first. A readable structure often makes the actual problem easier to spot, whether by eye or by a linter.
  • Keep your ESLint configuration file committed to the repository so every contributor’s editor enforces the same rules.
  • Revisit your ESLint rule set occasionally as a team, since priorities and code patterns shift as a project matures.

Frequently Asked Questions

Is a JavaScript formatter the same thing as ESLint?
No. A formatter improves readability through indentation and spacing. ESLint checks your code for potential bugs, unused variables, and style rule violations. They solve different problems, they run at different moments, and neither one replaces the other.

Can formatted JavaScript still fail ESLint checks?
Yes, and this happens constantly. Formatting only reorganizes whitespace, it does not touch the actual logic. A file can look perfectly tidy and still contain an unused variable, a risky comparison, or other issues that only ESLint would catch.

Does ESLint fix errors automatically?
Some ESLint rules can auto-fix straightforward issues, but many require a human decision, since fixing an unused variable or a logic issue often depends on understanding what the code was actually supposed to do.

What is the difference between ESLint and Prettier?
Prettier formats code, adjusting indentation and spacing for readability. ESLint lints code, checking for potential bugs and code quality issues. Most modern JavaScript projects use both together, with Prettier handling formatting and ESLint’s formatting-related rules turned off to avoid conflicts.

Should I use ESLint even on a small personal project?
Generally yes, since it catches subtle mistakes early, an unused import, an accidental global variable, that are easy to miss by eye, even in a project only you will ever touch.

Do I need to configure ESLint myself, or does it work out of the box?
ESLint ships with sensible defaults, but most teams customize the rule set to match their own priorities, since not every default rule will matter equally to every project.

Can a JavaScript formatter catch unused variables?
No. A formatter only adjusts spacing and indentation. Detecting an unused variable requires actually analyzing how the code is used, which is exactly what a linter like ESLint is built to do.

Why did ESLint flag something that still works fine when I run it?
JavaScript is forgiving about many patterns that are still considered risky or unclear, like loose equality comparisons or implicit type coercion. ESLint flags these because they can behave unexpectedly under different inputs, even if the current test case happens to work.

Is it bad practice to ship JavaScript that has not been linted?
It is not automatically broken, since the engine tolerates a lot, but skipping linting means subtle bugs and risky patterns can go unnoticed until they cause a real, harder-to-diagnose problem later.

Can I use a formatter and ESLint on the same file without conflicts?
Yes, as long as they are configured correctly. The standard approach turns off ESLint’s own formatting-related rules and lets a dedicated formatter, like Prettier, own that responsibility entirely, which avoids the two tools disagreeing with each other.

Clean-looking JavaScript and correct JavaScript are two different achievements, and mixing them up is an easy trap to fall into since both tools operate on the same files and both produce results that feel like quality control. A formatter earns its keep every day, quietly making scripts easier to read. ESLint earns its keep by catching the kinds of mistakes that a clean, readable file can still be hiding.

Neither tool is more important than the other. They just show up at different points in the same process, and knowing which one to reach for saves you from spending an afternoon staring at indentation when the actual problem was a comparison operator that never should have used loose equality.

The Same Distinction Applies to Your HTML and CSS

If this formatter-versus-linter confusion sounds familiar, it is because the same logic shows up across the front end. ToolMato’s HTML Formatter and CSS Formatter handle readability for markup and styles the same way this tool handles it for JavaScript, and both benefit from a dedicated validator or linter for the errors formatting alone will never reveal.

If you are staring at a script right now trying to figure out which category your problem falls into, start by formatting it. Try ToolMato’s JavaScript Formatter and see how much of the mystery clears up before you even reach for a linter.
🍅 Slug copied to clipboard successfully!