Tl;dr: you don't "need" to, but in current versions of ESLint, you'll need either a separate formatter (recommended) or third-party lint plugin to enforce formatting.
There are two kinds of tools in play here that are structurally different and better at different tasks. Speaking to how these tools work in the web ecosystem:
- Formatters generally only apply changes to code trivia/whitespace that don't impact runtime, such as tabs vs. spaces or when to insert newlines. They run very quickly because they don't have to deal with code logic and can reformat each file in one pass.
- Linters generally run a set of discrete rules that can understand code logic. They can be very powerful and change logic for the better, but are slower because lint rules have to think more (especially when you enable more advanced features such as typescript-eslint's linting with type information) and re-run if any fixes are applied automatically.
The line used to be more blurry because ESLint used to provide and recommend rules that enforced formatting. This was nice because you could use one tool for both formatting and linting - and because each lint rule is configurable, you could customize your formatting preferences very granularly.
However, because lint rules each deal with a unique area of logic and all have to be re-run if any fix is auto-applied, formatting with a linter is notoriously slow, prone to missed edge cases, and difficult for the lint teams to work with. Most lint teams now recommend against using a linter for formatting:
As mentioned at the end of both posts, if you really prefer to use ESLint for formatting, you can use the eslint.style plugin. It provides lint rules that enforce formatting preferences.