Claude-skill-registry eslint-flat-config
ESLint 9.x flat configuration patterns. Use when setting up ESLint with TypeScript.
install
source · Clone the upstream repo
git clone https://github.com/majiayu000/claude-skill-registry
Claude Code · Install into ~/.claude/skills/
T=$(mktemp -d) && git clone --depth=1 https://github.com/majiayu000/claude-skill-registry "$T" && mkdir -p ~/.claude/skills && cp -r "$T/skills/data/eslint-flat-config" ~/.claude/skills/majiayu000-claude-skill-registry-eslint-flat-config && rm -rf "$T"
manifest:
skills/data/eslint-flat-config/SKILL.mdsource content
ESLint Flat Config Skill
This skill covers ESLint 9.x flat configuration for TypeScript projects.
When to Use
Use this skill when:
- Setting up ESLint for TypeScript projects
- Migrating from legacy .eslintrc to flat config
- Configuring strict linting rules
- Integrating ESLint with Prettier
Core Principle
FLAT CONFIG IS THE FUTURE - ESLint 9.x uses flat config (
eslint.config.ts) by default.
Basic Configuration
eslint.config.ts
import js from '@eslint/js'; import tseslint from 'typescript-eslint'; import type { Linter } from 'eslint'; const config: Linter.Config[] = [ // Ignore patterns { ignores: ['dist/**', 'node_modules/**', 'coverage/**'], }, // Base JavaScript rules js.configs.recommended, // TypeScript strict rules ...tseslint.configs.strictTypeChecked, // Custom rules for TypeScript files { files: ['**/*.ts', '**/*.tsx'], languageOptions: { parserOptions: { project: './tsconfig.json', tsconfigRootDir: import.meta.dirname, }, }, rules: { // Type safety '@typescript-eslint/no-explicit-any': 'error', '@typescript-eslint/no-unsafe-assignment': 'error', '@typescript-eslint/no-unsafe-member-access': 'error', '@typescript-eslint/no-unsafe-call': 'error', '@typescript-eslint/no-unsafe-return': 'error', '@typescript-eslint/no-unsafe-argument': 'error', // Code quality '@typescript-eslint/explicit-function-return-type': 'error', '@typescript-eslint/explicit-module-boundary-types': 'error', '@typescript-eslint/no-unused-vars': [ 'error', { argsIgnorePattern: '^_' }, ], // Strict boolean expressions '@typescript-eslint/strict-boolean-expressions': 'error', // No floating promises '@typescript-eslint/no-floating-promises': 'error', '@typescript-eslint/no-misused-promises': 'error', }, }, ]; export default config;
Installation
npm install -D eslint @eslint/js typescript-eslint
Package.json Scripts
{ "scripts": { "lint": "eslint .", "lint:fix": "eslint --fix ." } }
Key Rules Explained
Type Safety Rules
// @typescript-eslint/no-explicit-any: 'error' // ❌ Bad function process(data: any) { } // ✅ Good function process(data: unknown) { }
// @typescript-eslint/explicit-function-return-type: 'error' // ❌ Bad function add(a: number, b: number) { return a + b; } // ✅ Good function add(a: number, b: number): number { return a + b; }
// @typescript-eslint/strict-boolean-expressions: 'error' // ❌ Bad if (value) { } // ✅ Good if (value !== undefined && value !== null) { } if (typeof value === 'string' && value.length > 0) { }
Promise Handling Rules
// @typescript-eslint/no-floating-promises: 'error' // ❌ Bad - Promise ignored fetchData(); // ✅ Good - Promise handled await fetchData(); // or fetchData().catch(handleError); // or void fetchData(); // Explicitly ignored
// @typescript-eslint/no-misused-promises: 'error' // ❌ Bad - async function in non-async context const handlers = { onClick: async () => { }, // Error in some contexts }; // ✅ Good - wrap in non-async handler const handlers = { onClick: () => { void handleClick(); }, };
ESLint with Prettier
Installation
npm install -D eslint-config-prettier
Configuration
import js from '@eslint/js'; import tseslint from 'typescript-eslint'; import prettier from 'eslint-config-prettier'; const config = [ js.configs.recommended, ...tseslint.configs.strictTypeChecked, prettier, // Must be last to override other formatting rules { // Custom rules... }, ]; export default config;
File-Specific Configurations
const config = [ // All TypeScript files { files: ['**/*.ts', '**/*.tsx'], rules: { '@typescript-eslint/explicit-function-return-type': 'error', }, }, // Test files - relaxed rules { files: ['**/*.test.ts', '**/*.test.tsx', '**/__tests__/**'], rules: { '@typescript-eslint/no-explicit-any': 'off', '@typescript-eslint/no-unsafe-assignment': 'off', }, }, // Config files - CommonJS allowed { files: ['*.config.js', '*.config.cjs'], rules: { '@typescript-eslint/no-var-requires': 'off', }, }, ];
Custom Rule Configurations
Naming Conventions
{ rules: { '@typescript-eslint/naming-convention': [ 'error', // Variables: camelCase { selector: 'variable', format: ['camelCase', 'UPPER_CASE'], }, // Types: PascalCase { selector: 'typeLike', format: ['PascalCase'], }, // Interfaces: PascalCase, no I prefix { selector: 'interface', format: ['PascalCase'], custom: { regex: '^I[A-Z]', match: false, }, }, // Private members: underscore prefix { selector: 'memberLike', modifiers: ['private'], format: ['camelCase'], leadingUnderscore: 'require', }, ], }, }
Import Organization
npm install -D eslint-plugin-import
import importPlugin from 'eslint-plugin-import'; const config = [ { plugins: { import: importPlugin, }, rules: { 'import/order': [ 'error', { groups: [ 'builtin', 'external', 'internal', 'parent', 'sibling', 'index', ], 'newlines-between': 'always', alphabetize: { order: 'asc' }, }, ], 'import/no-duplicates': 'error', }, }, ];
Migration from Legacy Config
Old .eslintrc.json
{ "extends": [ "eslint:recommended", "plugin:@typescript-eslint/recommended" ], "rules": { "@typescript-eslint/no-explicit-any": "error" } }
New eslint.config.ts
import js from '@eslint/js'; import tseslint from 'typescript-eslint'; export default [ js.configs.recommended, ...tseslint.configs.recommended, { rules: { '@typescript-eslint/no-explicit-any': 'error', }, }, ];
Common Issues and Solutions
"Parsing error: Cannot read file tsconfig.json"
// Ensure tsconfigRootDir is set { languageOptions: { parserOptions: { project: './tsconfig.json', tsconfigRootDir: import.meta.dirname, }, }, }
"Definition for rule not found"
# Ensure all plugins are installed npm install -D @eslint/js typescript-eslint
Files Not Being Linted
// Check ignores pattern { ignores: ['dist/**', 'node_modules/**'], } // Ensure files pattern includes your files { files: ['**/*.ts', '**/*.tsx'], }
IDE Integration
VS Code Settings
{ "eslint.useFlatConfig": true, "eslint.validate": [ "javascript", "javascriptreact", "typescript", "typescriptreact" ], "editor.codeActionsOnSave": { "source.fixAll.eslint": true } }
Best Practices Summary
- Use TypeScript for eslint.config.ts
- Enable strictTypeChecked rules
- Put Prettier config last
- Relax rules for test files
- Set tsconfigRootDir properly
- Use file-specific configurations
- Configure VS Code for auto-fix
Code Review Checklist
- eslint.config.ts uses TypeScript
- strictTypeChecked rules enabled
- no-explicit-any set to error
- explicit-function-return-type enabled
- Prettier config is last
- Test files have relaxed rules
- Ignores dist and node_modules