Skip to content

chore: Eliminate as any casts in Game/index.ts with proper type definitions #96

Description

@nodots

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)

  1. Add undo field to BackgammonActivePlay type:
    undo?: { frames: BackgammonGame[] }
  2. Add offeredThisTurnBy to BackgammonCube type:
    offeredThisTurnBy?: BackgammonPlayer
  3. Add stateVersion to BackgammonGame if not already present:
    stateVersion: number

Phase 2: Eliminate casts in src/Game/index.ts

  1. Undo stack casts — Replace (game as any).activePlay with properly typed access now that types include undo
  2. Cube casts — Replace (game.cube as any).offeredThisTurnBy with direct access
  3. 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
  4. Move mutations — Create typed helper functions for move property updates

Phase 3: Verify

  1. Run npx tsc --noEmit — should compile with zero errors and zero as any
  2. Run full test suite to verify no regressions
  3. 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

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions