Перейти к содержимому

Project Setup — ESLint, Prettier, TypeScript, Husky

С ESLint v9 конфигурация переехала в eslint.config.js (flat config). Старый .eslintrc.* — deprecated.

Окно терминала
npm install -D \
eslint \
@eslint/js \
typescript-eslint \
eslint-plugin-react \
eslint-plugin-react-hooks \
eslint-plugin-react-refresh \
globals
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';
export default tseslint.config(
// Ignore patterns
{ ignores: ['dist', 'node_modules', '*.config.js'] },
// Base JS rules
js.configs.recommended,
// TypeScript rules
...tseslint.configs.recommendedTypeChecked,
{
languageOptions: {
parserOptions: {
project: true,
tsconfigRootDir: import.meta.dirname,
},
},
},
// React rules
{
files: ['**/*.{ts,tsx}'],
plugins: {
'react-hooks': reactHooks,
'react-refresh': reactRefresh,
},
languageOptions: {
globals: { ...globals.browser },
},
rules: {
// React Hooks
...reactHooks.configs.recommended.rules,
// React Refresh (Vite HMR)
'react-refresh/only-export-components': [
'warn',
{ allowConstantExport: true },
],
// TypeScript
'@typescript-eslint/no-unused-vars': [
'error',
{ argsIgnorePattern: '^_', varsIgnorePattern: '^_' },
],
'@typescript-eslint/no-explicit-any': 'error',
'@typescript-eslint/prefer-nullish-coalescing': 'error',
'@typescript-eslint/prefer-optional-chain': 'error',
'@typescript-eslint/no-floating-promises': 'error',
// General
'no-console': ['warn', { allow: ['warn', 'error'] }],
'prefer-const': 'error',
},
}
);
{
"scripts": {
"lint": "eslint .",
"lint:fix": "eslint . --fix"
}
}

Окно терминала
npm install -D prettier eslint-config-prettier
{
"semi": true,
"singleQuote": true,
"trailingComma": "es5",
"tabWidth": 2,
"printWidth": 100,
"bracketSpacing": true,
"arrowParens": "avoid",
"endOfLine": "lf",
"importOrder": [
"^react",
"^react-dom",
"<THIRD_PARTY_MODULES>",
"^@/(.*)$",
"^[./]"
]
}
dist
node_modules
*.lock
// eslint.config.js — добавить в конец
import prettierConfig from 'eslint-config-prettier';
export default tseslint.config(
// ... остальные правила
prettierConfig // отключает ESLint правила, конфликтующие с Prettier
);

Полный набор строгих опций в tsconfig.json:

{
"compilerOptions": {
/* Strict режим — включает все ниже */
"strict": true,
/* Составляющие strict: */
"strictNullChecks": true, // null/undefined не присваиваются другим типам
"strictFunctionTypes": true, // strict covariance для параметров функций
"strictPropertyInitialization": true, // свойства класса должны быть инициализированы
"noImplicitAny": true, // запрет неявного any
"noImplicitThis": true, // запрет this с типом any
/* Дополнительно рекомендуется: */
"noUnusedLocals": true, // ошибка на неиспользуемые переменные
"noUnusedParameters": true, // ошибка на неиспользуемые параметры
"exactOptionalPropertyTypes": true, // отличие undefined от optional
"noUncheckedIndexedAccess": true, // индекс возвращает T | undefined
"noImplicitOverride": true // явный override при переопределении методов
}
}
// ❌ Без strict
function getUser(id: string) {
return users.find(u => u.id === id); // User | undefined — но TypeScript не предупредит
}
const user = getUser('123');
console.log(user.name); // runtime error!
// ✅ Со strict
function getUser(id: string): User | undefined {
return users.find(u => u.id === id);
}
const user = getUser('123');
console.log(user?.name); // TypeScript требует optional chaining
// noUncheckedIndexedAccess
const arr = [1, 2, 3];
const item = arr[10]; // тип: number | undefined, не number
if (item !== undefined) {
console.log(item * 2); // OK
}

Pre-commit хуки — запускают линтер только на staged файлах.

Окно терминала
npm install -D husky lint-staged
# Инициализация husky
npx husky init
{
"scripts": {
"prepare": "husky"
},
"lint-staged": {
"*.{ts,tsx}": [
"eslint --fix",
"prettier --write"
],
"*.{js,json,css,md}": [
"prettier --write"
]
}
}
Окно терминала
npx lint-staged
Окно терминала
npx --no -- commitlint --edit "$1"
Окно терминала
# Установка commitlint
npm install -D @commitlint/config-conventional @commitlint/cli
# commitlint.config.ts
export default {
extends: ['@commitlint/config-conventional'],
};

Формат коммитов: type(scope): description

  • feat: add user profile page
  • fix(auth): handle expired tokens
  • refactor(stores): simplify UserStore

my-app/
.husky/
pre-commit # npx lint-staged
src/
eslint.config.js # ESLint flat config v9
.prettierrc # Prettier настройки
.prettierignore
tsconfig.json # strict TypeScript
commitlint.config.ts # optional
package.json # lint-staged config