name: Lint Cleanup
description: FIX ESLint errors safely without breaking code. Prefix unused variables with _, fix no-case-declarations, add default props, and verify builds after each batch. Use when lint cleanup is needed for easier refactoring & faster Claude Code editing.
Safe Lint Cleanup
Instructions
This skill provides safe patterns for fixing ESLint errors without breaking code.
Pre-Flight Checklist
BEFORE starting any lint cleanup:
# 1. Get baseline count
npm run lint 2>&1 | tail -5
# 2. Save full output for reference
npm run lint 2>&1 > /tmp/lint-output.txt
# 3. Verify build works
npm run build
# 4. Check git status (ensure clean state)
git status
Error Categories & Fixes
1. Unused Variables (@typescript-eslint/no-unused-vars)
Pattern 1: Prefix Unused Variables with _
This is the SAFEST fix - silences the error without changing logic:
// BEFORE (error)
const unusedVar = someValue
// AFTER (no error)
const _unusedVar = someValue
Pattern 2: Prefix Unused Function Parameters
// BEFORE
const handleClick = (event: MouseEvent) => {
// doesn't use event
}
// AFTER
const handleClick = (_event: MouseEvent) => {
// doesn't use event
}
Pattern 3: Destructuring with Rename
// BEFORE
const { unusedProp, usedProp } = options
// AFTER
const { unusedProp: _unusedProp, usedProp } = options
Pattern 4: Unused Type Imports
// BEFORE
import { SomeType, UsedType } from '@/types'
// AFTER
import type { SomeType as _SomeType, UsedType } from '@/types'
Pattern 5: Remove Completely Unused Imports
// BEFORE
import { ref, watch, computed } from 'vue' // watch never used
// AFTER
import { ref, computed } from 'vue'
2. Case Declarations (no-case-declarations)
Error: Unexpected lexical declaration in case block
Cause: Using const, let, or class directly in a case block without braces.
Fix: Wrap case block contents in {} to create block scope.
// BEFORE (error)
switch (type) {
case 'foo':
const value = computeValue() // ERROR!
doSomething(value)
break
case 'bar':
const other = computeOther() // ERROR!
doOther(other)
break
}
// AFTER (fixed)
switch (type) {
case 'foo': {
const value = computeValue()
doSomething(value)
break
}
case 'bar': {
const other = computeOther()
doOther(other)
break
}
}
Quick find pattern:
# Find files with case declarations errors
npm run lint 2>&1 | grep "no-case-declarations" -B1 | grep -E "^/" | sort -u
3. Vue Default Props (vue/require-default-prop)
Error: Prop 'X' requires default value to be set
Cause: Optional props without default values in Vue 3 <script setup>.
Fix: Use withDefaults() to provide default values.
<!-- BEFORE (error) -->
<script setup lang="ts">
interface Props {
title?: string
count?: number
items?: string[]
}
const props = defineProps<Props>()
</script>
<!-- AFTER (fixed) -->
<script setup lang="ts">
interface Props {
title?: string
count?: number
items?: string[]
}
const props = withDefaults(defineProps<Props>(), {
title: '',
count: 0,
items: () => [] // Use factory for arrays/objects
})
</script>
Default value rules:
- Primitives: Use direct value (
'',0,false,null) - Arrays: Use factory function
() => [] - Objects: Use factory function
() => ({})
4. Boolean Shorthand (vue/prefer-true-attribute-shorthand)
Error: Boolean attribute should be written in shorthand form
Cause: Using :prop="true" instead of just prop.
<!-- BEFORE (error) -->
<MyComponent :is-active="true" :show-header="true" />
<!-- AFTER (fixed) -->
<MyComponent is-active show-header />
5. Empty Object Types (@typescript-eslint/no-empty-object-type)
Error: The {} type is not recommended
Cause: Using {} as a type in TypeScript (especially in .d.ts files).
Fix: Use object or Record<string, never> instead, OR exclude .d.ts files:
// In eslint.config.js ignores:
ignores: ['**/*.d.ts']
6. ESLint Config Alignment
Problem: Files excluded from tsconfig.json but not from ESLint cause parsing errors.
Fix: Keep ESLint ignores aligned with tsconfig excludes:
// eslint.config.js
{
ignores: [
'node_modules/**',
'dist/**',
'**/*.d.ts',
// Match tsconfig.json exclude patterns:
'src/stories/**',
'src/composables/adapters/**',
'src/sync/**',
'src/utils/emojiDetection.ts',
'src/utils/logger.ts',
// etc.
]
}
ESLint Config for Underscore Pattern
CRITICAL: The underscore pattern must be configured for BOTH .ts AND .vue files:
// eslint.config.js
// For TypeScript files
{
files: ['**/*.ts', '**/*.tsx'],
rules: {
'@typescript-eslint/no-unused-vars': ['error', {
argsIgnorePattern: '^_',
varsIgnorePattern: '^_',
caughtErrorsIgnorePattern: '^_'
}]
}
}
// For Vue files - MUST BE SEPARATE!
{
files: ['**/*.vue'],
rules: {
'@typescript-eslint/no-unused-vars': ['error', {
argsIgnorePattern: '^_',
varsIgnorePattern: '^_',
caughtErrorsIgnorePattern: '^_'
}]
}
}
Verification Process
After every batch of fixes:
# 1. Run build
npm run build 2>&1 | tail -10
# 2. Check new lint count
npm run lint 2>&1 | tail -5
# 3. Calculate progress
# (baseline - current) / baseline * 100 = % fixed
Files to Be Careful With
| File Type | Reason |
|-----------|--------|
| Vue components with templates | Variables might be used in template |
| Store files | Exported functions might appear unused |
| Composables | Returned values might appear unused |
| Test files | May have intentional unused vars |
| .d.ts files | Type declarations may use special patterns |
Error Priority Order
Fix errors in this order (highest impact first):
- Parsing errors - ESLint ignores alignment with tsconfig
- no-case-declarations - Structural fixes, wrap in
{} - require-default-prop - Add
withDefaults() - no-unused-vars - Prefix with
_or remove - prefer-true-attribute-shorthand - Simple template fixes
- no-explicit-any - Requires proper typing (lower priority)
Quick Reference Commands
# Get current lint count
npm run lint 2>&1 | tail -5
# Save full output
npm run lint 2>&1 > /tmp/lint-output.txt
# Find files with specific error
npm run lint 2>&1 | grep "ERROR_NAME" -B1 | grep -E "^/" | sort -u
# Count specific error type
grep "ERROR_NAME" /tmp/lint-output.txt | wc -l
# Check specific file errors
cat /tmp/lint-output.txt | grep -A20 "YourFile.vue$" | head -25
# Run --fix for auto-fixable errors (safe)
npm run lint -- --fix
# Find case declarations by file
awk '/^\/home.*\.(vue|ts)$/ { file=$0 } /no-case-declarations/ { print file }' /tmp/lint-output.txt | sort -u
Common Gotchas
- Multiple Matches: Add more surrounding context to make match unique
- Variable Used in Template: Check
<template>section before prefixing - Exported but Appears Unused: Don't prefix exports - used externally
- Store/Composable Return Values: Check if values are returned for consumers
- Case Block Fallthrough: Ensure
breakis inside the{}braces - Factory Functions for Props: Arrays/objects need
() => []not[]
See lint-cleanup-guide.md for complete documentation.
Expert Next.js App Router
Developpement
Un skill qui transforme Claude en expert Next.js App Router.
Générateur de README
Developpement
Crée des README.md professionnels et complets pour vos projets.
Rédacteur de Documentation API
Developpement
Génère de la documentation API complète au format OpenAPI/Swagger.