[priority: critical] 13+ files use as any type casts bypassing TypeScript's type safety #98

Closed
opened 2026-05-20 10:59:25 +02:00 by Anexim · 2 comments
Owner

Severity: Critical — type casts hide real type errors, make data flow untraceable, and defeat the purpose of using TypeScript.

Findings:

  • gameHooks.ts has 7 as any casts (highest in codebase)
  • page.tsx has 6
  • craftingStore.ts has 2
  • crafting-design.ts has 6 explicit : any type annotations
  • effects.ts uses as unknown as GameState double cast — accepts partial state (4 fields) but passes to function expecting full GameState (71 fields)
  • 14 files total use explicit : any type annotations

Affected files:

  • src/app/page.tsx, src/app/components/LeftPanel.tsx
  • src/components/game/crafting/EnchantmentDesigner.tsx
  • src/components/game/tabs/SpireCombatPage/RoomDisplay.tsx, src/components/game/tabs/SpireCombatPage/SpireCombatPage.tsx
  • src/lib/game/crafting-design.ts, src/lib/game/crafting-apply.ts, src/lib/game/effects.ts
  • src/lib/game/stores/gameHooks.ts, src/lib/game/stores/craftingStore.ts, src/lib/game/stores/combat-actions.ts
  • src/lib/game/stores/gameActions.ts, src/lib/game/stores/gameLoopActions.ts, src/lib/game/stores/gameStore.ts
  • src/lib/game/effects/discipline-effects.ts, src/lib/game/effects/upgrade-effects.ts
  • src/lib/game/hooks/useGameDerived.ts, src/lib/game/utils/discipline-math.ts

Suggested fix: Systematically replace as any with proper types. For store state access, define proper interfaces. For cross-module boundaries, create shared type definitions. Refactor computeAllEffects to accept only the fields it actually needs.

Confidence: High
Dimension: type_safety (score: 58.0%) / logic_clarity

**Severity:** Critical — type casts hide real type errors, make data flow untraceable, and defeat the purpose of using TypeScript. **Findings:** - `gameHooks.ts` has 7 `as any` casts (highest in codebase) - `page.tsx` has 6 - `craftingStore.ts` has 2 - `crafting-design.ts` has 6 explicit `: any` type annotations - `effects.ts` uses `as unknown as GameState` double cast — accepts partial state (4 fields) but passes to function expecting full `GameState` (71 fields) - 14 files total use explicit `: any` type annotations **Affected files:** - `src/app/page.tsx`, `src/app/components/LeftPanel.tsx` - `src/components/game/crafting/EnchantmentDesigner.tsx` - `src/components/game/tabs/SpireCombatPage/RoomDisplay.tsx`, `src/components/game/tabs/SpireCombatPage/SpireCombatPage.tsx` - `src/lib/game/crafting-design.ts`, `src/lib/game/crafting-apply.ts`, `src/lib/game/effects.ts` - `src/lib/game/stores/gameHooks.ts`, `src/lib/game/stores/craftingStore.ts`, `src/lib/game/stores/combat-actions.ts` - `src/lib/game/stores/gameActions.ts`, `src/lib/game/stores/gameLoopActions.ts`, `src/lib/game/stores/gameStore.ts` - `src/lib/game/effects/discipline-effects.ts`, `src/lib/game/effects/upgrade-effects.ts` - `src/lib/game/hooks/useGameDerived.ts`, `src/lib/game/utils/discipline-math.ts` **Suggested fix:** Systematically replace `as any` with proper types. For store state access, define proper interfaces. For cross-module boundaries, create shared type definitions. Refactor `computeAllEffects` to accept only the fields it actually needs. **Confidence:** High **Dimension:** type_safety (score: 58.0%) / logic_clarity
Anexim added the ai:todo label 2026-05-20 10:59:25 +02:00
n8n-gitea was assigned by Anexim 2026-05-20 10:59:25 +02:00
Author
Owner

Starting work on eliminating as any type casts. Will systematically find and replace with proper types across all affected files.

Starting work on eliminating `as any` type casts. Will systematically find and replace with proper types across all affected files.
Author
Owner

Fixed. Eliminated as any and explicit : any type casts across 18 source files.

Changes made:

  • effects/discipline-effects.ts — Changed computeDisciplineEffects() signature to accept optional DisciplineStoreState instead of GameState (the parameter was unused internally)
  • effects.ts — Removed GameState dependency from computeAllEffects() and getUnifiedEffects(), fixed import path for ComputedEffects
  • stores/gameHooks.ts — Removed all 7 as any casts by using proper UnifiedEffects type and calling computeDisciplineEffects() without args
  • app/page.tsx — Removed 6 as any casts, used UnifiedEffects type, fixed grimoire spell rendering to use correct SpellDef properties (elem instead of element, dmg instead of power, effects instead of effect)
  • crafting-design.ts — Replaced 6 explicit : any annotations with ComputedEffects, DesignProgress | null, EquipmentInstance
  • crafting-apply.ts — Replaced computedEffects: any with ComputedEffects
  • crafting-actions/design-actions.ts — Replaced let updates: any with Partial<GameState>
  • stores/combat-actions.ts, gameActions.ts, gameLoopActions.ts, gameStore.ts — Removed as any from computeDisciplineEffects() calls
  • stores/craftingStore.ts — Replaced slot as any with slot as EquipmentSlot
  • app/components/LeftPanel.tsx — Removed as any from upgradeEffects.meditationEfficiency
  • components/crafting/EnchantmentDesigner.tsx — Replaced allowedEquipmentCategories: any[] with EquipmentCategory[]
  • components/tabs/SpireCombatPage/RoomDisplay.tsx — Removed as any from roomType and floorState casts
  • components/tabs/SpireCombatPage/SpireCombatPage.tsx — Removed 3 as any casts
  • components/tabs/StatsTab/CombatStatsSection.tsx — Replaced activeSpellDef: any with SpellDef | null
  • components/tabs/StatsTab/ManaStatsSection.tsx — Created proper ManaStatsEffects interface extending ComputedEffects
  • components/tabs/StatsTab/ElementStatsSection.tsx — Replaced : any with ElementState type
  • components/tabs/StatsTab/LoopStatsSection.tsx — Replaced : any with SpellState type
  • utils/activity-log.ts — Replaced eventType as any with eventType as ActivityEventType

Remaining: 1 as any in craftingStore.ts (line 212) — pre-existing architectural mismatch between CraftingStore and GameState types that was previously masked. Fixing properly would require refactoring the entire crafting action layer.

Verification: 638/639 tests pass (1 pre-existing failure in spire-utils.test.ts). All modified files under 400-line limit.

✅ Fixed. Eliminated `as any` and explicit `: any` type casts across 18 source files. **Changes made:** - `effects/discipline-effects.ts` — Changed `computeDisciplineEffects()` signature to accept optional `DisciplineStoreState` instead of `GameState` (the parameter was unused internally) - `effects.ts` — Removed `GameState` dependency from `computeAllEffects()` and `getUnifiedEffects()`, fixed import path for `ComputedEffects` - `stores/gameHooks.ts` — Removed all 7 `as any` casts by using proper `UnifiedEffects` type and calling `computeDisciplineEffects()` without args - `app/page.tsx` — Removed 6 `as any` casts, used `UnifiedEffects` type, fixed grimoire spell rendering to use correct `SpellDef` properties (`elem` instead of `element`, `dmg` instead of `power`, `effects` instead of `effect`) - `crafting-design.ts` — Replaced 6 explicit `: any` annotations with `ComputedEffects`, `DesignProgress | null`, `EquipmentInstance` - `crafting-apply.ts` — Replaced `computedEffects: any` with `ComputedEffects` - `crafting-actions/design-actions.ts` — Replaced `let updates: any` with `Partial<GameState>` - `stores/combat-actions.ts`, `gameActions.ts`, `gameLoopActions.ts`, `gameStore.ts` — Removed `as any` from `computeDisciplineEffects()` calls - `stores/craftingStore.ts` — Replaced `slot as any` with `slot as EquipmentSlot` - `app/components/LeftPanel.tsx` — Removed `as any` from `upgradeEffects.meditationEfficiency` - `components/crafting/EnchantmentDesigner.tsx` — Replaced `allowedEquipmentCategories: any[]` with `EquipmentCategory[]` - `components/tabs/SpireCombatPage/RoomDisplay.tsx` — Removed `as any` from `roomType` and `floorState` casts - `components/tabs/SpireCombatPage/SpireCombatPage.tsx` — Removed 3 `as any` casts - `components/tabs/StatsTab/CombatStatsSection.tsx` — Replaced `activeSpellDef: any` with `SpellDef | null` - `components/tabs/StatsTab/ManaStatsSection.tsx` — Created proper `ManaStatsEffects` interface extending `ComputedEffects` - `components/tabs/StatsTab/ElementStatsSection.tsx` — Replaced `: any` with `ElementState` type - `components/tabs/StatsTab/LoopStatsSection.tsx` — Replaced `: any` with `SpellState` type - `utils/activity-log.ts` — Replaced `eventType as any` with `eventType as ActivityEventType` **Remaining:** 1 `as any` in `craftingStore.ts` (line 212) — pre-existing architectural mismatch between `CraftingStore` and `GameState` types that was previously masked. Fixing properly would require refactoring the entire crafting action layer. **Verification:** 638/639 tests pass (1 pre-existing failure in `spire-utils.test.ts`). All modified files under 400-line limit.
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: Anexim/Mana-Loop#98