Skip to content

ESLint Configuration

Complete guide to ESLint configuration and customization in the TypeScript Project Template.

Overview

The template uses ESLint 9 with the modern flat configuration format, providing:

  • TypeScript integration with type checking
  • Prettier integration for formatting
  • Import organization rules
  • Jest-specific rules for test files

Configuration File (eslint.config.js)

Basic Structure

javascript
import typescriptParser from '@typescript-eslint/parser';
import typescript from '@typescript-eslint/eslint-plugin';
import prettierPlugin from 'eslint-plugin-prettier';

export default [
  {
    files: ['**/*.{js,mjs,cjs,ts}'],
    languageOptions: {
      parser: typescriptParser,
      parserOptions: {
        project: './tsconfig.json'
      }
    },
    plugins: {
      '@typescript-eslint': typescript,
      prettier: prettierPlugin
    },
    rules: {
      // TypeScript rules
      '@typescript-eslint/no-explicit-any': 'error',
      '@typescript-eslint/explicit-function-return-type': 'warn',
      
      // Prettier integration
      'prettier/prettier': 'error'
    }
  }
];

Key Rules Explained

TypeScript Rules

@typescript-eslint/no-explicit-any

typescript
// ❌ Bad - explicit any
function process(data: any): any {
  return data;
}

// ✅ Good - proper types
function process<T>(data: T): T {
  return data;
}

@typescript-eslint/explicit-function-return-type

typescript
// ❌ Bad - implicit return type
export async function main() {
  console.log('Hello');
}

// ✅ Good - explicit return type
export async function main(): Promise<void> {
  console.log('Hello');
}

Import Rules

import/order

typescript
// ✅ Good - organized imports
import fs from 'fs';
import path from 'path';

import { someUtility } from './utils.js';
import { SomeType } from './types.js';

Code Quality Rules

no-console

typescript
// ✅ Allowed in this template for demonstration
console.log('Application started');

// For production, consider using a logger
import { logger } from './logger.js';
logger.info('Application started');

Running ESLint

Basic Commands

bash
# Check for linting issues
npm run lint

# Fix auto-fixable issues
npm run lint:fix

# Check specific files
npx eslint src/index.ts

# Debug configuration
npx eslint --print-config src/index.ts

IDE Integration

VS Code Settings

json
{
  "eslint.validate": ["typescript"],
  "editor.codeActionsOnSave": {
    "source.fixAll.eslint": true
  }
}

Customization

Adding New Rules

javascript
export default [
  {
    // ... existing configuration
    rules: {
      // Add custom rules
      'no-unused-vars': 'error',
      'prefer-const': 'error',
      '@typescript-eslint/no-unused-vars': 'error'
    }
  }
];

File-Specific Rules

javascript
export default [
  // Main configuration
  {
    files: ['**/*.{js,mjs,cjs,ts}'],
    // ... main rules
  },
  
  // Test-specific rules
  {
    files: ['**/*.test.ts', '**/*.spec.ts'],
    rules: {
      '@typescript-eslint/no-explicit-any': 'off' // Allow any in tests
    }
  }
];

Environment-Specific Configuration

javascript
export default [
  {
    files: ['**/*.{js,mjs,cjs,ts}'],
    languageOptions: {
      globals: {
        // Node.js globals
        process: 'readonly',
        Buffer: 'readonly',
        
        // Jest globals (for test files)
        describe: 'readonly',
        it: 'readonly',
        expect: 'readonly'
      }
    }
  }
];

Troubleshooting

Common Issues

Parser Configuration Errors

bash
# Error: Cannot find module '@typescript-eslint/parser'
npm install --save-dev @typescript-eslint/parser @typescript-eslint/eslint-plugin

# Error: Project configuration not found
# Ensure tsconfig.json exists and is valid
npx tsc --noEmit

Rule Conflicts

javascript
// Disable conflicting rules
export default [
  {
    rules: {
      // Disable if conflicts with Prettier
      'indent': 'off',
      '@typescript-eslint/indent': 'off'
    }
  }
];

Performance Issues

javascript
export default [
  {
    languageOptions: {
      parserOptions: {
        project: './tsconfig.json',
        // Improve performance
        createDefaultProgram: false
      }
    }
  }
];

Advanced Configuration

Custom Plugins

javascript
import customPlugin from 'eslint-plugin-custom';

export default [
  {
    plugins: {
      custom: customPlugin
    },
    rules: {
      'custom/rule-name': 'error'
    }
  }
];

Shared Configurations

javascript
// eslint.base.js
export const baseConfig = {
  languageOptions: {
    parser: typescriptParser
  },
  plugins: {
    '@typescript-eslint': typescript
  }
};

// eslint.config.js
import { baseConfig } from './eslint.base.js';

export default [
  {
    ...baseConfig,
    files: ['**/*.ts'],
    rules: {
      // Project-specific rules
    }
  }
];

Ignoring Files

javascript
export default [
  {
    ignores: [
      'dist/**',
      'coverage/**',
      'node_modules/**',
      '*.config.js'
    ]
  },
  // ... other configurations
];

Integration with Other Tools

Prettier Integration

javascript
export default [
  {
    plugins: {
      prettier: prettierPlugin
    },
    rules: {
      'prettier/prettier': 'error'
    }
  }
];

Jest Integration

javascript
export default [
  {
    files: ['**/*.test.ts'],
    languageOptions: {
      globals: {
        describe: 'readonly',
        it: 'readonly',
        expect: 'readonly',
        beforeEach: 'readonly',
        afterEach: 'readonly'
      }
    }
  }
];

TypeScript Integration

javascript
export default [
  {
    languageOptions: {
      parser: typescriptParser,
      parserOptions: {
        project: './tsconfig.json',
        tsconfigRootDir: import.meta.dirname
      }
    }
  }
];

Best Practices

Rule Selection

  • Start with recommended configurations
  • Add rules gradually based on team needs
  • Document custom rules and their purpose
  • Review rules regularly for relevance

Performance Optimization

  • Use type-aware rules sparingly
  • Exclude unnecessary files from linting
  • Cache results in CI/CD environments
  • Run incrementally during development

Team Collaboration

  • Share configuration across team members
  • Document exceptions and their reasons
  • Use consistent IDE settings
  • Regular rule reviews in team meetings

Migration Guide

From ESLint 8

  1. Update configuration to flat format
  2. Replace extends with explicit plugin imports
  3. Update ignore patterns to new format
  4. Test configuration thoroughly

Adding New Rules

  1. Research rule purpose and impact
  2. Test on existing code before enforcing
  3. Document rule rationale for team
  4. Consider gradual rollout for breaking rules

Released under the MIT License.