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
- Update configuration to flat format
- Replace extends with explicit plugin imports
- Update ignore patterns to new format
- Test configuration thoroughly
Adding New Rules
- Research rule purpose and impact
- Test on existing code before enforcing
- Document rule rationale for team
- Consider gradual rollout for breaking rules