type State = { player: { x: number; y: number }; score: number };
const actions = defineActions<State>()({
move: (s, dx: number, dy: number) => ({
...s,
player: { x: s.player.x + dx, y: s.player.y + dy },
}),
addScore: (s, points: number) => ({ ...s, score: s.score + points }),
});
// Later:
const game = createGame({ state: initial, actions });
game.actions.move(5, 0); // typed: (dx: number, dy: number) => void
game.actions.addScore(100); // typed: (points: number) => void
Define a typed action map for a known state type
S.Why is it called twice?
defineActions<State>()(actions)is a curried call. The first call fixesS; the second infers each action's argument tuple. Without the split, TS would have to either widen state tounknownor force you to retypeSin every action — either is worse.