Skip to content
This repository has been archived by the owner on Mar 5, 2023. It is now read-only.

useService support #69

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions .changeset/hungry-waves-kneel.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'xstate-codegen': patch
---

Add <Id>Interpreter helper type for useService typing
14 changes: 12 additions & 2 deletions packages/xstate-compiled/examples/trafficLightMachine.machine.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { Machine, interpret } from '@xstate/compiled';
import { useMachine } from '@xstate/compiled/react';
import { Machine, interpret, LightMachineInterpreter } from '@xstate/compiled';
import { useMachine, useService } from '@xstate/compiled/react';

type LightEvent =
| { type: 'TIMER' }
Expand Down Expand Up @@ -95,3 +95,13 @@ const interpretTrafficLightMachine = () => {
);
return interpreter;
};

type LightMachineService = LightMachineInterpreter<LightContext, LightEvent>;

const useTrafficLightService = (service: LightMachineService) => {
const [state, send] = useService(service);
state.matches('green');
// @ts-expect-error
state.matches('wrong');
return [state, send];
};
38 changes: 36 additions & 2 deletions packages/xstate-compiled/readme.md
Original file line number Diff line number Diff line change
Expand Up @@ -37,13 +37,47 @@ You must pass three type options to `createMachine/Machine`:
For instance:

```ts
import { Machine } from '@xstate/compiled';
import { Machine, UniqueIdInterpreter } from '@xstate/compiled';

interface Context {}

type Event = { type: 'DUMMY_TYPE' };

const machine = Machine<Context, Event, 'uniqueId'>({});
const machine = Machine<Context, Event, 'uniqueId'>({
states: {
first: {}
second: {}
}
});

type UniqueIdService = UniqueIdInterpreter<Context, Event>
```

### React support

For use with React you can import `useMachine` from `@xstate/compiled/react` instead for better type support.

Namely the `state.matches()` will type check against state schema properly.

```ts
import { useMachine } from '@xstate/compiled/react';

const [state, send, service] = useMachine(machine); // machine from previous example
state.matches('first'); // correctly type checked
state.matches('wrong'); // produces error
```

The `service` variable is useful to be passed to other components either through props or context.
Notice in the first example how we have declared `UniqueIdService`. You can use that type in such cases.

```ts
import { useService } from '@xstate/compiled/react';

function UniqueComponent({ service }: { service: UniqueIdService }) {
const [state] = useService(service);
state.matches('first'); // correctly type checked
state.matches('wrong'); // produces error
}
```

## Options
Expand Down
2 changes: 2 additions & 0 deletions packages/xstate-compiled/src/templates/index.d.ts.hbs
Original file line number Diff line number Diff line change
Expand Up @@ -157,6 +157,8 @@ declare module '@xstate/compiled' {
>['_options']>
): this;
}

export type {{capitalize this.id}}Interpreter<TContext, TEvent extends EventObject> = InterpreterWithMatches<TContext, {}, TEvent, '{{ this.id}}'>
{{/each}}

export interface RegisteredMachinesMap<TContext, TEvent extends EventObject> {
Expand Down