Phase 3.1: Remove duplicate Awakening interface - Removed unused src/lib/types/Awakening.d.ts - Using entities.ts as single source of truth for Awakening type - Awakening now properly uses LocalizedName interface - No breaking changes (unused file had zero imports) 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
9.4 KiB
TypeScript Quality Improvement Plan
Status: 0 TypeScript errors achieved (151 → 0) Next Phase: Code quality and maintainability improvements
Overview
While we've eliminated all TypeScript errors, several opportunities exist to improve type safety, reduce workarounds, and enhance maintainability.
Phase 1: Critical Type Safety (High Priority)
1.1 Remove Type Assertions in Component Props
Problem: Using as any to spread props loses type safety
Files:
src/lib/components/uncap/UncapIndicator.svelte(lines 167, 169)src/lib/components/ui/segmented-control/SegmentedControl.svelte(line 88)
Tasks:
- Create proper union type for StarRender props
- Define TranscendenceStarProps and UncapStarProps interfaces
- Replace
{...(star.props as any)}with properly typed spread - Create typed wrapper for RadioGroupPrimitive or fix optionalProps spreading
Acceptance Criteria:
- No
as anycasts in component prop spreading - Full IntelliSense support for star component props
- Type errors caught at compile time
Effort: Medium (4-6 hours)
1.2 Unify Visibility Types
Problem: Number/string mismatch between frontend and API requiring runtime conversion
Files:
src/lib/types/api/party.ts(visibility: number)src/lib/api/adapters/party.adapter.ts(visibility: string literal)src/lib/services/party.service.ts(runtime mapping)
Tasks:
- Create PartyVisibility enum/const
- Update Party type to use string literals
- Remove number-to-string mapping in party.service.ts
- Update all visibility references across codebase
- Update API serialization if needed
Acceptance Criteria:
- Single source of truth for visibility values
- No runtime type conversion needed
- Type safety when setting visibility
Effort: Medium (3-4 hours)
Impact: Prevents invalid visibility values at compile time
Phase 2: Third-Party Library Improvements (Medium Priority)
2.1 Create bits-ui Wrapper Components
Problem: Using optionalProps() workaround for type incompatibilities
Files:
src/lib/components/ui/Select.sveltesrc/lib/components/ui/segmented-control/SegmentedControl.sveltesrc/lib/components/ui/RadioGroup.svelte(if exists)
Tasks:
- Create
src/lib/components/ui/bits-ui-wrappers/directory - Create SelectRoot wrapper with explicit prop typing
- Create RadioGroupRoot wrapper with explicit prop typing
- Update consuming components to use wrappers
- Document why wrappers exist (bits-ui type issues)
Acceptance Criteria:
- No
optionalProps()calls for bits-ui components - Clear prop types for each wrapper
- Wrappers forward only supported props
Effort: Medium (4-5 hours)
2.2 Add wx-svelte-grid Type Definitions
Problem: Missing Cell export causing workaround with loose types
Files:
src/lib/components/database/cells/LastUpdatedCell.svelte- Other cell components using wx-svelte-grid
Tasks:
- Create
src/lib/types/wx-svelte-grid.d.ts - Define Cell, Grid, and other used types
- Replace
[key: string]: anywith proper Cell interface - Update all cell components to use typed Cell props
Acceptance Criteria:
- Proper Cell type available for import
- No
[key: string]: anyin cell components - IntelliSense support for grid props
Effort: Small (2-3 hours)
Phase 3: Type Consolidation (Medium Priority)
3.1 Consolidate Awakening Types
Problem: Two different Awakening interfaces exist
Files:
src/lib/types/Awakening.d.tssrc/lib/types/api/entities.ts
Tasks:
- Compare both definitions and identify differences
- Choose canonical location (prefer entities.ts)
- Remove duplicate definition
- Update all imports to use single source
- Ensure LocalizedName is properly defined
Acceptance Criteria:
- Single Awakening type definition
- All imports use same source
- No breaking changes to existing code
Effort: Small (1-2 hours)
3.2 Type the any Usages
Problem: Loose typing in services and adapters
Files to audit:
grep -r ": any" src/lib --include="*.ts" --include="*.svelte"
Common patterns to fix:
row: any→row: DatabaseRow(or specific entity type)item: any→item: GridItemmapped: any→mapped: CreatePartyParamsresult: any→ proper return type- Context types using
any
Tasks:
- Audit all
anyusages and categorize - Create proper types for common patterns (DatabaseRow, GridItem, etc.)
- Replace
anywith specific types - Add generics where appropriate
Acceptance Criteria:
- Minimal
anyusage (only where truly necessary) - Clear justification comment for remaining
anyusages - Improved IntelliSense throughout codebase
Effort: Large (6-8 hours)
Phase 4: Test Infrastructure (Low Priority)
4.1 Create Test Mock Factories
Problem: Test mocks are brittle and require manual updates when types change
Files:
src/lib/api/adapters/__tests__/entity.adapter.test.tssrc/lib/api/adapters/__tests__/grid.adapter.test.ts- Other test files
Tasks:
- Create
src/lib/testing/factories.ts - Implement
createMockWeapon(overrides?) - Implement
createMockCharacter(overrides?) - Implement
createMockSummon(overrides?) - Implement
createMockParty(overrides?) - Update all tests to use factories
- Add JSDoc examples for each factory
Acceptance Criteria:
- All test mocks use factory functions
- Overrides supported for customization
- Type-safe mock creation
- Tests resilient to type changes
Effort: Medium (4-5 hours)
4.2 Improve Test Coverage for Type Transformations
Focus areas:
- Visibility mapping (number → string)
- Awakening type handling
- Party payload transformations
- Grid item CRUD operations
Tasks:
- Add tests for mapToApiPayload visibility conversion
- Add tests for awakening null/undefined handling
- Test edge cases in type transformations
- Document expected type contracts in tests
Effort: Medium (3-4 hours)
Phase 5: Code Quality (Low Priority)
5.1 Address TypeScript Warnings
Current status: 190 warnings
Categories to review:
- Unused CSS selectors
- Non-reactive updates
- Accessibility warnings
- Import warnings
Tasks:
- Run
pnpm check 2>&1 | grep "Warn:" | sort | uniq -c - Categorize warnings by type and severity
- Fix or suppress unused CSS warnings
- Review non-reactive update warnings (may indicate bugs)
- Address accessibility issues
Acceptance Criteria:
- Warnings reduced by 50% or more
- All critical warnings addressed
- Suppressions documented with reason
Effort: Medium (4-6 hours)
5.2 Add JSDoc Documentation
Problem: Complex type transformations lack explanation
Target areas:
mapToApiPayload()in party.service.ts- Visibility mapping logic
- Type assertion workarounds
- Third-party wrapper purposes
Tasks:
- Document visibility mapping with TODO for unification
- Explain why type assertions are needed
- Add examples to complex type transformations
- Document third-party library workarounds
Acceptance Criteria:
- All workarounds have explanation comments
- Complex transformations documented
- TODOs added for future improvements
Effort: Small (2-3 hours)
5.3 Strict Null Checks Review
Problem: Some null handling is implicit or unclear
Tasks:
- Review null coalescing operators (
??) - Document what empty string defaults mean
- Consider making related properties required together (e.g., avatar.picture + avatar.element)
- Add validation for undefined vs null semantics
Effort: Small (2-3 hours)
Implementation Strategy
Recommended Order:
Week 1: Critical Type Safety
- Remove type assertions in UncapIndicator (1.1)
- Unify visibility types (1.2)
Week 2: Third-Party Libraries 3. Create bits-ui wrappers (2.1) 4. Add wx-svelte-grid types (2.2)
Week 3: Type Consolidation
5. Consolidate Awakening types (3.1)
6. Type the any usages (3.2) - ongoing
Week 4: Polish 7. Create test factories (4.1) 8. Address warnings (5.1) 9. Add JSDoc (5.2)
Success Metrics:
- Type Safety: 0
as anycasts (except documented cases) - Consistency: Single source of truth for shared types
- Maintainability: Test factories, JSDoc, reduced warnings
- Developer Experience: Better IntelliSense, clearer errors
Non-Goals:
- Perfect type coverage (pragmatic > perfect)
- Rewriting working code just for types
- Over-engineering simple components
Notes
Philosophy:
- Incremental improvement over big rewrites
- Document "why" for workarounds
- Type safety where it adds value
- Pragmatic trade-offs are okay
When to Use any:
- Truly dynamic data (rare)
- Third-party library gaps (with comment)
- Overly complex generic inference
- Always add
// eslint-disable-next-line @typescript-eslint/no-explicit-anyand justification
When to Create Wrappers:
- Type incompatibilities we can't fix upstream
- Need to restrict API surface
- Want better defaults
- Shared configuration across usages
Progress Tracking
- Phase 1: Critical Type Safety (0/2)
- Phase 2: Third-Party Libraries (0/2)
- Phase 3: Type Consolidation (0/2)
- Phase 4: Test Infrastructure (0/2)
- Phase 5: Code Quality (0/3)
Last Updated: 2025-11-28 Current Status: Planning phase