Skip to content

Replace FarmhandReducers stub class with typed ReducerMethods interface #699

Description

@jeremyckahn

Problem

src/components/Farmhand/FarmhandReducers.tsx is a class that extends Component and contains 50+ stub methods that all throw "Unimplemented". At runtime, matching reducer functions replace these stubs. This pattern adds indirection, uses any[] for all method parameters, and has a TODO comment on line 31 that says: "TODO: Replace this with a TypeScript interface."

The current code:

export class FarmhandReducers extends Component<FarmhandProps, FarmhandState> {
  addCowToInventory(...args: any[]) {
    throw new Error("Unimplemented")
  }
  addPeer(...args: any[]) {
    throw new Error("Unimplemented")
  }
  // ... 50+ more stub methods
}

Implementation Plan

Step 1: Define a ReducerMethods interface

Create an interface in src/components/Farmhand/FarmhandReducers.tsx that matches all 50+ reducer method signatures. Each reducer follows the pattern (state: farmhand.state, ...optionalArgs) => farmhand.state.

export interface ReducerMethods {
  addCowToInventory: (state: farmhand.state) => farmhand.state
  addPeer: (state: farmhand.state) => farmhand.state
  adjustLoan: (state: farmhand.state, amount: number) => farmhand.state
  changeCowAutomaticHugState: (state: farmhand.state, cowId: string, enabled: boolean) => farmhand.state
  // ... all 50+ methods with correct signatures
}

To get the correct signatures, look at the reducer implementations in src/game-logic/reducers/. Each exported reducer function defines the parameter types.

Step 2: Create a bound reducers object

Instead of the class with stubs, create a plain object that maps method names to bound reducer functions:

import * as reducers from "../../game-logic/reducers/index.js"

export const reducerMethods: ReducerMethods = {
  addCowToInventory: reducers.addCowToInventory.bind(null),
  addPeer: reducers.addPeer.bind(null),
  // ... all methods
}

Step 3: Update Farmhand component to use the interface directly

The Farmhand component (in src/components/Farmhand/Farmhand.tsx) uses useFarmhand hook which currently interacts with the FarmhandReducers class. Update the hook to work with the ReducerMethods interface directly.

Step 4: Remove the FarmhandReducers class

Delete the FarmhandReducers class entirely, keeping only the ReducerMethods interface and the bound object.

Step 5: Run type checker

npm run check:types

Acceptance Criteria

  • ReducerMethods interface is defined with all 50+ method signatures matching the reducers in src/game-logic/reducers/
  • FarmhandReducers class is removed (no more stub methods with any[])
  • All reducer methods are bound to the Farmhand instance via a plain object
  • Zero any[] parameter lists remain in the reducer binding code
  • npm run check:types passes with no errors
  • npm test passes

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or request

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions