ESLint Configuration for TypeScript React Project
This document outlines the ESLint configuration used in our TypeScript React project. It provides a robust set of rules and plugins to ensure code quality and consistency.
Table of Contents
Overview
Our ESLint configuration is designed for a TypeScript React project using Vite. It incorporates rules for TypeScript, React, React Hooks, Vitest (for testing), and includes additional plugins for import sorting, accessibility, and code formatting.
Prerequisites
Node.js (version 14 or later recommended)
Yarn or npm
A TypeScript React project (preferably using Vite)
Installation
Install the required dependencies by running the following command in your project root:
yarn add -D eslint @typescript-eslint/eslint-plugin @typescript-eslint/parser eslint-plugin-react eslint-plugin-react-hooks eslint-plugin-vitest eslint-plugin-testing-library eslint-plugin-import eslint-plugin-jsx-a11y eslint-plugin-prettier eslint-config-prettier eslint-import-resolver-typescript
Here’s a brief description of each package:
eslint: The core ESLint library@typescript-eslint/eslint-plugin: ESLint plugin which provides rules for TypeScript codebases@typescript-eslint/parser: An ESLint parser which leverages TypeScript ESTree to allow for ESLint to lint TypeScript source codeeslint-plugin-react: React specific linting rules for ESLinteslint-plugin-react-hooks: ESLint plugin which provides rules for React Hookseslint-plugin-vitest: ESLint plugin for Vitest, a Vite-native testing frameworkeslint-plugin-testing-library: ESLint plugin for Testing Library, providing rules to follow Testing Library best practiceseslint-plugin-import: ESLint plugin with rules that help validate proper importseslint-plugin-jsx-a11y: Static AST checker for accessibility rules on JSX elementseslint-plugin-prettier: Runs Prettier as an ESLint rule and reports differences as individual ESLint issueseslint-config-prettier: Turns off all rules that are unnecessary or might conflict with Prettiereslint-import-resolver-typescript: This plugin adds TypeScript support toeslint-plugin-import
Configuration File
Create a file named eslint.config.js in your project root with the following content:
import { fixupPluginRules } from '@eslint/compat';
import typescript from '@typescript-eslint/eslint-plugin';
import typescriptParser from '@typescript-eslint/parser';
import react from 'eslint-plugin-react';
import reactHooks from 'eslint-plugin-react-hooks';
import vitestPlugin from 'eslint-plugin-vitest';
import testingLibrary from 'eslint-plugin-testing-library';
import importPlugin from 'eslint-plugin-import';
import jsxA11y from 'eslint-plugin-jsx-a11y';
import prettier from 'eslint-plugin-prettier';
import prettierConfig from 'eslint-config-prettier';
export default [
{
files: ['src/**/*.{ts,tsx}'],
ignores: ['**/dist/**', '**/node_modules/**', '**/coverage/**'],
languageOptions: {
parser: typescriptParser,
parserOptions: {
ecmaVersion: 'latest',
sourceType: 'module',
project: './tsconfig.json',
},
},
plugins: {
'@typescript-eslint': fixupPluginRules(typescript),
react: fixupPluginRules(react),
'react-hooks': fixupPluginRules(reactHooks),
vitest: fixupPluginRules(vitestPlugin),
'testing-library': fixupPluginRules(testingLibrary),
import: fixupPluginRules(importPlugin),
'jsx-a11y': fixupPluginRules(jsxA11y),
prettier,
},
settings: {
react: {
version: 'detect',
},
'import/parsers': {
'@typescript-eslint/parser': ['.ts', '.tsx'],
},
'import/resolver': {
typescript: {
alwaysTryTypes: true,
project: './tsconfig.json',
},
},
},
rules: {
...typescript.configs.recommended.rules,
...react.configs.recommended.rules,
...reactHooks.configs.recommended.rules,
...vitestPlugin.configs.recommended.rules,
...testingLibrary.configs.react.rules,
...importPlugin.configs.recommended.rules,
...jsxA11y.configs.recommended.rules,
...prettierConfig.rules,
'prettier/prettier': 'error',
'react/react-in-jsx-scope': 'off',
'react/jsx-uses-react': 'off',
'@typescript-eslint/explicit-module-boundary-types': 'off',
'@typescript-eslint/no-unused-vars': ['error', { argsIgnorePattern: '^_' }],
'react-hooks/exhaustive-deps': 'warn',
'import/no-unresolved': 'error',
'import/default': 'off',
'import/no-named-as-default': 'off',
'import/no-named-as-default-member': 'off',
'import/order': [
'error',
{
groups: ['builtin', 'external', 'internal', 'parent', 'sibling', 'index'],
'newlines-between': 'always',
alphabetize: { order: 'asc', caseInsensitive: true },
},
],
'jsx-a11y/anchor-is-valid': [
'error',
{
components: ['Link'],
specialLink: ['to'],
},
],
},
},
{
files: ['src/**/*.test.{ts,tsx}'],
rules: {
'@typescript-eslint/no-explicit-any': 'off',
'vitest/expect-expect': 'error',
'vitest/no-disabled-tests': 'warn',
'vitest/no-focused-tests': 'error',
'testing-library/await-async-queries': 'error',
'testing-library/no-await-sync-queries': 'error',
'testing-library/no-debugging-utils': 'warn',
'testing-library/no-dom-import': 'off',
},
},
{
files: ['*.config.ts', 'vite.config.ts'],
rules: {
'import/no-extraneous-dependencies': 'off',
},
},
];