This document explains the ESLint rules added to prevent TypeScript anti-patterns and improve type safety.
These rules prevent dangerous type casting patterns that can lead to runtime errors:
- Purpose: Prevents dangerous object literal type assertions
- Example: Prevents
{ foo: 'bar' } as ComplexType - Rationale: Object literal assertions can hide missing properties
- no-unsafe-argument: Prevents passing
anyto typed parameters - no-unsafe-assignment: Prevents assigning
anyto typed variables - no-unsafe-call: Prevents calling
anyas a function - no-unsafe-member-access: Prevents accessing properties on
any - no-unsafe-return: Prevents returning
anyfrom typed functions
Example of prevented anti-pattern:
// ❌ BAD - This would now be an ESLint error
function handleParams(args: Record<string, unknown>) {
const typedParams = args as MyToolParams; // Unsafe casting
return typedParams.someProperty as string; // Unsafe member access
}
// ✅ GOOD - Proper validation approach
function handleParams(args: Record<string, unknown>) {
const typedParams = MyToolParamsSchema.parse(args); // Runtime validation
return typedParams.someProperty; // Type-safe access
}- Purpose: Prevents unsafe TypeScript comments
- Blocks:
@ts-ignore,@ts-nocheck - Allows:
@ts-expect-error(with description)
These rules encourage modern TypeScript patterns but don't block builds:
- Purpose: Prefer
??over||for default values - Example:
value ?? 'default'instead ofvalue || 'default' - Rationale: More precise handling of falsy values (0, '', false)
- Purpose: Prefer
?.for safe property access - Example:
obj?.propinstead ofobj && obj.prop - Rationale: More concise and readable
- Purpose: Prefer
as constfor literal types - Example:
['a', 'b'] as constinstead of['a', 'b'] as string[]
Test files (.test.ts) have relaxed rules for flexibility:
- All
no-unsafe-*rules are disabled no-explicit-anyis disabled- Tests often need to test error conditions and edge cases
- 387 total issues detected
- 207 errors: Require fixing for type safety
- 180 warnings: Can be gradually improved
- Phase 1 (Immediate): Error-level rules prevent new anti-patterns
- Phase 2 (Ongoing): Gradually fix warning-level violations
- Phase 3 (Future): Consider promoting warnings to errors
- Prevents Regression: New code can't introduce the anti-patterns we just fixed
- Runtime Safety: Catches potential runtime errors at compile time
- Code Quality: Encourages modern TypeScript best practices
- Developer Experience: Better IDE support and autocomplete
These rules prevent the specific anti-patterns identified in PR review:
- ✅ Type Casting in Parameters:
args as SomeTypepatterns now flagged - ✅ Unsafe Property Access:
params.field as stringpatterns prevented - ✅ Missing Validation: Encourages schema validation over casting
- ✅ Return Type Mismatches: Function signature inconsistencies caught
- ✅ Nullish Coalescing: Promotes safer default value handling
When fixing ESLint issues across the codebase:
- Deploy Multiple Agents: Run agents in parallel on different files
- Single File Focus: Each agent works on ONE tool file at a time
- Individual Linting: Agents run
npm run lint path/to/single/file.tsonly - Immediate Commits: Commit each agent's work as soon as they complete
- Never Wait: Don't wait for all agents to finish before committing
- Avoid Full Linting: Never run
npm run lintwithout a file path (eats context) - Progress Tracking: Update todo list and periodically check overall status
- Loop Until Done: Keep deploying agents until all issues are resolved
# Single file linting (what agents should run)
npm run lint src/mcp/tools/device-project/test_device_proj.ts
# NOT this (too much context)
npm run lint- Individual commits: One commit per agent completion
- Clear messages:
fix: resolve ESLint errors in tool_name.ts - Never batch: Don't wait to commit multiple files together
- Progress preservation: Each fix is immediately saved
Consider adding these rules in future iterations:
@typescript-eslint/strict-boolean-expressions: Stricter boolean logic@typescript-eslint/prefer-reduce-type-parameter: Better generic usage@typescript-eslint/switch-exhaustiveness-check: Complete switch statements