Skip to content

Commit

Permalink
add typestate type to service returned from react/fsm useMachine
Browse files Browse the repository at this point in the history
  • Loading branch information
lukekarrys committed Feb 18, 2021
1 parent 2ba323b commit 7e1a1a5
Show file tree
Hide file tree
Showing 2 changed files with 60 additions and 8 deletions.
12 changes: 5 additions & 7 deletions packages/xstate-react/src/fsm.ts
Original file line number Diff line number Diff line change
Expand Up @@ -36,8 +36,8 @@ export function useMachine<
}
): [
StateMachine.State<TContext, TEvent, TState>,
StateMachine.Service<TContext, TEvent>['send'],
StateMachine.Service<TContext, TEvent>
StateMachine.Service<TContext, TEvent, TState>['send'],
StateMachine.Service<TContext, TEvent, TState>
] {
if (process.env.NODE_ENV !== 'production') {
const [initialMachine] = useState(stateMachine);
Expand Down Expand Up @@ -88,11 +88,9 @@ export function useService<
StateMachine.Service<TContext, TEvent, TState>['send'],
StateMachine.Service<TContext, TEvent, TState>
] {
const subscription: Subscription<StateMachine.State<
TContext,
TEvent,
TState
>> = useMemo(() => {
const subscription: Subscription<
StateMachine.State<TContext, TEvent, TState>
> = useMemo(() => {
let currentState = getServiceState(service);

return {
Expand Down
56 changes: 55 additions & 1 deletion packages/xstate-react/test/useMachine-fsm.test.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import * as React from 'react';
import { useMachine } from '../src/fsm';
import { createMachine, assign, interpret } from '@xstate/fsm';
import { createMachine, assign, interpret, StateMachine } from '@xstate/fsm';
import {
render,
fireEvent,
Expand Down Expand Up @@ -268,4 +268,58 @@ describe('useMachine hook for fsm', () => {
service.send('EV');
expect(flag).toBe(true);
});

// Example from: https://github.com/davidkpiano/xstate/discussions/1944
it('fsm useMachine service should be typed correctly', () => {
interface Context {
count?: number;
}

type Event = { type: 'READY' };

type State =
| {
value: 'idle';
context: Context & {
count: undefined;
};
}
| {
value: 'ready';
context: Context & {
count: number;
};
};

type Service = StateMachine.Service<Context, Event, State>;

const machine = createMachine<Context, Event, State>({
id: 'machine',
initial: 'idle',
context: {
count: undefined
},
states: {
idle: {},
ready: {}
}
});

const useCustomService = (service: Service) =>
React.useEffect(() => {}, [service]);

function App() {
const [, , service] = useMachine(machine);

useCustomService(service);

return null;
}

const noop = (_val: any) => {
/* ... */
};

noop(App);
});
});

0 comments on commit 7e1a1a5

Please sign in to comment.