Right, let’s talk about making your code not just correct, but presentable. You’ve got TypeScript telling you your types are wrong, but who tells you your formatting is a mess? You could rely on your own impeccable taste and consistency, but I don’t, and I’m guessing you don’t either. That’s where Prettier comes in. It’s the opinionated code formatter that takes your beautifully functional but visually chaotic code and makes it… well, consistent. It stops all the pointless arguments about semicolons and single quotes in their tracks by simply making the decision for everyone. It’s a dictator, but a benevolent one.

The magic of Prettier is that it completely divorces formatting from linting. ESLint has rules about how code should look (quotes, semi), but it shouldn’t. Its job is to find problematic patterns. Prettier’s only job is to make your code pretty. You run them together, but they have separate responsibilities. The goal is to set up Prettier to handle all formatting (the aesthetics) and configure ESLint to focus solely on code quality (the logic). This synergy is what we’re after.

The Core Setup: It’s Simpler Than You Think

First, install the necessary packages. We need Prettier itself and the crucial ESLint config that makes the two play nice together.

npm install --save-dev prettier eslint-config-prettier

eslint-config-prettier is the key. Its entire job is to turn off all ESLint rules that are unnecessary or might conflict with Prettier. It’s the diplomat that prevents a formatting turf war in your editor.

Now, create a .prettierrc file. This is where you state your few, precious overrides to Prettier’s default opinions. Most of the time, the defaults are spot-on. A simple one looks like this:

{
  "semi": true,
  "singleQuote": true,
  "tabWidth": 2,
  "trailingComma": "es5"
}

And that’s mostly it. The real trick is in your .eslintrc.js config. You need to extend the eslint-config-prettier config. This must come last in your extends array. I’ll say it again: last. This ensures it overrides any formatting rules from other configs you might be using, like @typescript-eslint/recommended.

// .eslintrc.js
module.exports = {
  extends: [
    'eslint:recommended',
    '@typescript-eslint/recommended',
    'prettier' // This MUST be last. This is the way.
  ],
  // ... other rules and parser options
};

The Editor Integration: Where the Magic Happens

Installing packages is one thing, but the real quality-of-life improvement happens in your editor (VS Code, I assume?). You’ll want the Prettier extension. The critical setting to enable is Editor: Format On Save. Now, when you save, Prettier instantly reformats your document according to your rules.

But here’s a pro tip: also set "editor.defaultFormatter" to "esbenp.prettier-vscode" for your TypeScript and JavaScript files. This ensures VS Code uses Prettier and not some other built-in formatter that might get in the way.

// In your VSCode settings.json
"editor.formatOnSave": true,
"[typescript]": {
  "editor.defaultFormatter": "esbenp.prettier-vscode"
},
"[javascript]": {
  "editor.defaultFormatter": "esbenp.prettier-vscode"
}

The One “Gotcha”: The Order of Operations

There’s a classic pitfall here that will make you question your sanity. You save your file and… you get an ESLint error about formatting? I thought we turned those off!

This is almost always a problem of order of operations. Your editor is running Prettier on save, which reformats the file. But then it runs ESLint, which might still have some active formatting rules that Prettier just violated. The solution is to ensure your ESLint config is properly extending the prettier config last, as shown above. If you’ve done that and it’s still happening, you might need to restart your editor’s ESLint server or check for a deeply nested config somewhere else in your project.

Pre-commit Hooks: Enforcing the Law

You can’t rely on everyone having their editor set up correctly. This is where pre-commit hooks come in. Using something like lint-staged and husky, you can automatically format all staged files before they’re committed. This is the final gatekeeper, ensuring no unformatted code ever makes it into your repository.

// package.json
{
  "lint-staged": {
    "*.{ts,js,json,md}": "prettier --write"
  }
}

The command prettier --write will reformat the files in place. When combined with a pre-commit hook, it means every commit is automatically formatted, regardless of how the author wrote it. It’s authoritarian, but it works.

So there you have it. Prettier handles the style, ESLint handles the substance. You get clean, consistent code without the endless bike-shedding. It’s one of the best investments you can make in your project’s long-term sanity. Now go forth and stop worrying about where your curly braces go.