ข้ามไปเนื้อหาหลัก

Category: reference

ESLint + Prettier Configuration — TypeScript Project Setup

ตั้งค่า ESLint + Prettier ที่ทำงานร่วมกันได้สำหรับ TypeScript project: rules, integrations, pre-commit hooks

· อ่านประมาณ 2 นาที

สารบัญ

Install

# ESLint + TypeScript support
npm install --save-dev eslint @eslint/js typescript-eslint

# Prettier + ESLint integration
npm install --save-dev prettier eslint-config-prettier

# Pre-commit hooks
npm install --save-dev lint-staged husky

ESLint Config (Flat Config — ESLint 9+)

// eslint.config.js
import js from '@eslint/js';
import tseslint from 'typescript-eslint';
import prettier from 'eslint-config-prettier';

export default tseslint.config(
  js.configs.recommended,
  ...tseslint.configs.recommended,
  ...tseslint.configs.recommendedTypeChecked,
  prettier,  // ต้องอยู่ท้ายสุด — disable rules ที่ clash กับ Prettier
  {
    languageOptions: {
      parserOptions: {
        project: true,
        tsconfigRootDir: import.meta.dirname,
      },
    },
    rules: {
      // TypeScript
      '@typescript-eslint/no-explicit-any': 'warn',
      '@typescript-eslint/no-unused-vars': ['error', { argsIgnorePattern: '^_' }],
      '@typescript-eslint/prefer-nullish-coalescing': 'error',
      '@typescript-eslint/no-floating-promises': 'error',

      // General
      'no-console': ['warn', { allow: ['warn', 'error'] }],
      'prefer-const': 'error',
    },
  },
  {
    // ไม่ตรวจไฟล์เหล่านี้
    ignores: ['dist/**', 'node_modules/**', '*.config.js', '*.config.ts'],
  },
);

ESLint Flat Config (Legacy — ESLint 8)

// .eslintrc.cjs
module.exports = {
  root: true,
  parser: '@typescript-eslint/parser',
  parserOptions: {
    project: './tsconfig.json',
    ecmaVersion: 'latest',
    sourceType: 'module',
  },
  plugins: ['@typescript-eslint'],
  extends: [
    'eslint:recommended',
    'plugin:@typescript-eslint/recommended',
    'plugin:@typescript-eslint/recommended-type-checked',
    'prettier',  // ต้องอยู่ท้ายสุด
  ],
  rules: {
    '@typescript-eslint/no-explicit-any': 'warn',
    '@typescript-eslint/no-unused-vars': ['error', { argsIgnorePattern: '^_' }],
    'no-console': ['warn', { allow: ['warn', 'error'] }],
  },
  ignorePatterns: ['dist/', 'node_modules/'],
};

Prettier Config

// .prettierrc
{
  "semi": true,
  "singleQuote": true,
  "printWidth": 100,
  "tabWidth": 2,
  "useTabs": false,
  "trailingComma": "all",
  "bracketSpacing": true,
  "arrowParens": "always",
  "endOfLine": "lf"
}
# .prettierignore
dist/
node_modules/
*.min.js
*.min.css
package-lock.json

Astro-specific Config

npm install --save-dev eslint-plugin-astro @typescript-eslint/parser
// eslint.config.js
import astro from 'eslint-plugin-astro';

export default tseslint.config(
  ...astro.configs.recommended,
  {
    files: ['**/*.astro'],
    languageOptions: {
      parser: astroParser,
      parserOptions: { parser: '@typescript-eslint/parser' },
    },
  },
);

package.json Scripts

{
  "scripts": {
    "lint": "eslint src --ext .ts,.tsx,.astro",
    "lint:fix": "eslint src --ext .ts,.tsx,.astro --fix",
    "format": "prettier --write .",
    "format:check": "prettier --check ."
  }
}

Pre-commit Hooks ด้วย lint-staged + husky

# Setup husky
npx husky init

# เพิ่ม pre-commit hook
echo "npx lint-staged" > .husky/pre-commit
// package.json
{
  "lint-staged": {
    "*.{ts,tsx,astro}": ["eslint --fix", "prettier --write"],
    "*.{css,json,md}": ["prettier --write"]
  }
}

ทุกครั้งที่ git commit จะ lint + format เฉพาะไฟล์ที่ staged อัตโนมัติ


VS Code Integration

// .vscode/settings.json
{
  "editor.defaultFormatter": "esbenp.prettier-vscode",
  "editor.formatOnSave": true,
  "editor.codeActionsOnSave": {
    "source.fixAll.eslint": "explicit"
  },
  "eslint.validate": ["javascript", "typescript", "astro"],
  "[astro]": {
    "editor.defaultFormatter": "astro-build.astro-vscode"
  }
}
// .vscode/extensions.json
{
  "recommendations": [
    "dbaeumer.vscode-eslint",
    "esbenp.prettier-vscode",
    "astro-build.astro-vscode"
  ]
}

Rules ที่ควรรู้

// Rules ที่ useful มาก
{
  // ไม่ let ถ้าไม่มีการ reassign
  'prefer-const': 'error',

  // ห้ามใช้ == (ใช้ === เท่านั้น)
  'eqeqeq': ['error', 'always'],

  // ไม่ return await ใน async function (ยกเว้น try/catch)
  '@typescript-eslint/return-await': ['error', 'in-try-catch'],

  // consistent type import
  '@typescript-eslint/consistent-type-imports': ['error', {
    prefer: 'type-imports',
    fixStyle: 'inline-type-imports',
  }],

  // ห้ามใช้ require() ใน ESM
  '@typescript-eslint/no-require-imports': 'error',
}

TypeScript ที่ตรวจโดย ESLint vs TypeScript Compiler

ตรวจโดยตัวอย่าง
TypeScript compilertype mismatch, missing properties
ESLint rulesno-floating-promises, prefer-nullish-coalescing
Prettierformatting, indentation, semicolons

ไม่ต้องให้ ESLint ทำงานซ้ำกับ TypeScript compiler — ใช้ ESLint เพื่อ enforce patterns ที่ TS ไม่ตรวจ