generated at
XStateで型安全なStateを表現する例
from XState


examplesを見ても「state毎に別の型を定義する」というのを表現している例が見当たらない
これがギリ近い、けど違う
数分docsを読んだ程度なのでもっと良い書き方があるかもしれない


ts
type TodoState = | { type: 'ACTIVE'; value: readonly Item[] } | { type: 'INACTIVE'; value: readonly [] }; type TodoEvent = | { type: 'ADD'; item: Item } | { type: 'TOGGLE'; id: number } | { type: 'DISABLE' } | { type: 'ENABLE' }; type Item = { id: number; name: string; completed: boolean; };
↑Stateを2種類に分けている

↓の
contextの部分で state: のように包む必要がある
そうすると毎度、 ...context.state のようなものが必要になる
本当はでデフォルトで context: {type:..,value:..} と書けるべきである
だが、そうするとactions内で型エラーが頻出して面倒なことになる
ts
export const machine = createMachine({ initial: 'ACTIVE', types: {} as { events: TodoEvent; context: { state: TodoState }; }, context: { state: { type: 'INACTIVE', value: [], }, }, states: { ACTIVE: { on: { ADD: { target: 'ACTIVE', actions: assign({ state: ({ context, event }) => ({ type: 'ACTIVE', value: [...context.state.value, event.item], }) as const, }), }, TOGGLE: { target: 'ACTIVE', actions: assign({ state: ({ context, event }) => ({ type: 'ACTIVE', value: context.state.value.map(item => item.id === event.id ? { ...item, completed: !item.completed } : item, ), }) as const, }), }, DISABLE: { target: 'INACTIVE', actions: assign({ state: () => ({ type: 'INACTIVE', value: [], }) as const, }), }, }, }, INACTIVE: { on: { ENABLE: 'ACTIVE', }, }, }, });