Problem
src/Game/index.ts contains 46 as any casts on the feat/4.6.4-RC branch. These bypass TypeScript's type safety and mask potential runtime bugs. Key categories:
1. Undo stack (activePlay.undo) — ~6 casts
The undo feature stores undo.frames on activePlay, but BackgammonActivePlay doesn't define an undo field, forcing (game as any).activePlay patterns everywhere.
2. Doubling cube offeredThisTurnBy — ~3 casts
The per-turn repeat-double guard uses (game.cube as any).offeredThisTurnBy because the BackgammonCube type doesn't include this field.
3. Game/Play state assertions — ~11 casts
Generic return types from state transitions are cast to any instead of using proper discriminated union narrowing.
4. Move property modifications — ~11 casts
Mutating move properties via as any instead of using typed builder patterns.
5. Generic return type casts — ~5 casts
Functions returning as any to satisfy return type constraints.
Implementation Plan
Phase 1: Update @nodots-llc/backgammon-types (prerequisite)
- Add
undo field to BackgammonActivePlay type:
undo?: { frames: BackgammonGame[] }
- Add
offeredThisTurnBy to BackgammonCube type:
offeredThisTurnBy?: BackgammonPlayer
- Add
stateVersion to BackgammonGame if not already present:
Phase 2: Eliminate casts in src/Game/index.ts
- Undo stack casts — Replace
(game as any).activePlay with properly typed access now that types include undo
- Cube casts — Replace
(game.cube as any).offeredThisTurnBy with direct access
- State transition returns — Use TypeScript discriminated unions and type guards instead of
as any casts. Example:
// Before
return { ...game, stateKind: 'moved' } as any
// After
return { ...game, stateKind: 'moved' as const } satisfies BackgammonGameMoved
- Move mutations — Create typed helper functions for move property updates
Phase 3: Verify
- Run
npx tsc --noEmit — should compile with zero errors and zero as any
- Run full test suite to verify no regressions
- Search for remaining
as any and document any that are truly necessary (e.g., third-party lib interop)
Files to modify
../types/src/ — type definitions (Phase 1)
src/Game/index.ts — remove casts (Phase 2)
src/Play/index.ts — may have related casts
Problem
src/Game/index.tscontains 46as anycasts on thefeat/4.6.4-RCbranch. These bypass TypeScript's type safety and mask potential runtime bugs. Key categories:1. Undo stack (
activePlay.undo) — ~6 castsThe undo feature stores
undo.framesonactivePlay, butBackgammonActivePlaydoesn't define anundofield, forcing(game as any).activePlaypatterns everywhere.2. Doubling cube
offeredThisTurnBy— ~3 castsThe per-turn repeat-double guard uses
(game.cube as any).offeredThisTurnBybecause theBackgammonCubetype doesn't include this field.3. Game/Play state assertions — ~11 casts
Generic return types from state transitions are cast to
anyinstead of using proper discriminated union narrowing.4. Move property modifications — ~11 casts
Mutating move properties via
as anyinstead of using typed builder patterns.5. Generic return type casts — ~5 casts
Functions returning
as anyto satisfy return type constraints.Implementation Plan
Phase 1: Update
@nodots-llc/backgammon-types(prerequisite)undofield toBackgammonActivePlaytype:offeredThisTurnBytoBackgammonCubetype:offeredThisTurnBy?: BackgammonPlayerstateVersiontoBackgammonGameif not already present:stateVersion: numberPhase 2: Eliminate casts in
src/Game/index.ts(game as any).activePlaywith properly typed access now that types includeundo(game.cube as any).offeredThisTurnBywith direct accessas anycasts. Example:Phase 3: Verify
npx tsc --noEmit— should compile with zero errors and zeroas anyas anyand document any that are truly necessary (e.g., third-party lib interop)Files to modify
../types/src/— type definitions (Phase 1)src/Game/index.ts— remove casts (Phase 2)src/Play/index.ts— may have related casts