DEV Community

Jordan Sandford
Jordan Sandford

Posted on

Set up eslint, prettier and ts quickly

I wanted to set eslint along with prettier in a new ts project with the latest instructions. I was getting wrong/hallucinated results from AI search, many articles had outdated information and finally, the official documentation was not as clear as it could have been.

The confusion in the official docs was around whether the 'plugins' section in eslint.config.js was needed when using the 'extends' section. It wasn't needed (for this basic configuration), as 'extends' items automatically pull in rules and plugins, etc.

It turned out to be pretty straight forward, and here's a step by step guide helping you to do it in just a few minutes!

Install eslint and typescript-eslint.

From typescript-eslint.io/getting-started and typescript-eslint.io: use with prettier

  1. bunx create-vite some-project-name and choose something with TypeScript. I chose framework: React, variant: typescript, use rolldown-vite: No, Install with bun: Yes.
  2. Depending on what you select when running the previous line, this line may not be needed: bun add eslint @eslint/js typescript typescript-eslint
  3. For vscode integration, install dbaeumer.vscode-eslint ("eslint" from Microsoft)

Next, install Prettier.

From prettier.io/docs/install and github.com/prettier/eslint-config-prettier

  1. bun add --dev --exact prettier
  2. bun --eval "fs.writeFileSync('.prettierrc','{}\n')"
  3. bun --eval "fs.writeFileSync('.prettierignore','# Ignore artifacts:\nbuild\ncoverage\n')"
  4. bunx prettier . --check
  5. bun add --dev eslint-config-prettier
  6. bunx eslint-config-prettier eslint.config.js (makes sure eslint is working)

Wrap up by setting up a husky pre-commit hook!

This will prettify all staged files automatically. Also from prettier.io/docs/install.

  1. bun --eval "fs.writeFileSync('.husky/pre-commit','bunx lint-staged\n')"
  2. bunx husky init
  3. bun add --dev husky lint-staged
  4. Add the lint-staged property to package.json (see below)
  5. For vscode integration, install esbenp.prettier-vscode ("prettier-vscode" from prettier.io/Prettier)

I generally like to commit the empty project at this point.

package.json

{
  "name": "some-project-name",
  "private": true,
  "version": "0.0.0",
  "type": "module",
  "scripts": {
    "dev": "vite",
    "build": "tsc -b && vite build",
    "lint": "eslint .",
    "preview": "vite preview",
    "prepare": "husky"
  },
  "lint-staged": {
    "**/*": "prettier --write --ignore-unknown"
  },
  "dependencies": {
    "react": "^19.2.0",
    "react-dom": "^19.2.0"
  },
  "devDependencies": {
    "@eslint/js": "^9.39.2",
    "@types/node": "^24.10.1",
    "@types/react": "^19.2.5",
    "@types/react-dom": "^19.2.3",
    "@vitejs/plugin-react": "^5.1.1",
    "eslint": "^9.39.2",
    "eslint-config-prettier": "^10.1.8",
    "eslint-plugin-react-hooks": "^7.0.1",
    "eslint-plugin-react-refresh": "^0.4.24",
    "globals": "^16.5.0",
    "husky": "^9.1.7",
    "lint-staged": "^16.2.7",
    "prettier": "3.7.4",
    "typescript": "^5.9.3",
    "typescript-eslint": "^8.53.0",
    "vite": "^7.2.4"
  }
}
Enter fullscreen mode Exit fullscreen mode

eslint.config.js

import js from "@eslint/js";
import globals from "globals";
import reactHooks from "eslint-plugin-react-hooks";
import reactRefresh from "eslint-plugin-react-refresh";
import tseslint from "typescript-eslint";
import { defineConfig, globalIgnores } from "eslint/config";
import eslintConfigPrettier from "eslint-config-prettier/flat";

export default defineConfig([
  globalIgnores(["dist"]),
  {
    files: ["**/*.{ts,tsx}"],
    extends: [
      js.configs.recommended,
      tseslint.configs.strict,
      tseslint.configs.stylistic,
      reactHooks.configs.flat.recommended,
      reactRefresh.configs.vite,
      eslintConfigPrettier,
    ],
    languageOptions: {
      ecmaVersion: 2020,
      globals: globals.browser,
    },
  },
]);
Enter fullscreen mode Exit fullscreen mode

Top comments (0)