Skip to content

Commit

Permalink
Fixed ContextFrom and EventFrom types (#3104)
Browse files Browse the repository at this point in the history
  • Loading branch information
Andarist committed Mar 2, 2022
1 parent ae20405 commit 3706c62
Show file tree
Hide file tree
Showing 4 changed files with 146 additions and 8 deletions.
5 changes: 5 additions & 0 deletions .changeset/good-queens-cross.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'xstate': patch
---

Fixed `ContextFrom` helper type to work on typegened machines.
5 changes: 5 additions & 0 deletions .changeset/wet-insects-share.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'xstate': patch
---

Fixed `EventFrom` helper type to work on machines.
42 changes: 35 additions & 7 deletions packages/core/src/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1783,13 +1783,27 @@ export type EmittedFrom<T> = ReturnTypeOrValue<T> extends infer R
: never;

type ResolveEventType<T> = ReturnTypeOrValue<T> extends infer R
? R extends StateMachine<infer _, infer __, infer TEvent, infer ____>
? R extends StateMachine<
infer _,
infer __,
infer TEvent,
infer ___,
infer ____,
infer _____,
infer ______
>
? TEvent
: R extends Model<infer _, infer TEvent, infer ___, infer ____>
: R extends Model<infer _, infer TEvent, infer __, infer ___>
? TEvent
: R extends State<infer _, infer TEvent, infer ___, infer ____>
: R extends State<infer _, infer TEvent, infer __, infer ___, infer ____>
? TEvent
: R extends Interpreter<infer _, infer __, infer TEvent, infer ____>
: R extends Interpreter<
infer _,
infer __,
infer TEvent,
infer ___,
infer ____
>
? TEvent
: R extends ActorRef<infer TEvent, infer _>
? TEvent
Expand All @@ -1803,13 +1817,27 @@ export type EventFrom<
> = IsNever<K> extends true ? TEvent : Extract<TEvent, { type: K }>;

export type ContextFrom<T> = ReturnTypeOrValue<T> extends infer R
? R extends StateMachine<infer TContext, infer _, infer __, infer ___>
? R extends StateMachine<
infer TContext,
infer _,
infer __,
infer ___,
infer ____,
infer _____,
infer ______
>
? TContext
: R extends Model<infer TContext, infer _, infer __, infer ___>
? TContext
: R extends State<infer TContext, infer _, infer __, infer ___>
: R extends State<infer TContext, infer _, infer __, infer ___, infer ____>
? TContext
: R extends Interpreter<infer TContext, infer _, infer __, infer ___>
: R extends Interpreter<
infer TContext,
infer _,
infer __,
infer ___,
infer ____
>
? TContext
: never
: never;
102 changes: 101 additions & 1 deletion packages/core/test/typeHelpers.test.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,108 @@
import { assign, createMachine, EventFrom, MachineOptionsFrom } from '../src';
import {
assign,
ContextFrom,
createMachine,
EventFrom,
MachineOptionsFrom
} from '../src';
import { createModel } from '../src/model';
import { TypegenMeta } from '../src/typegenTypes';

describe('ContextFrom', () => {
it('should return context of a machine', () => {
const machine = createMachine({
schema: {
context: {} as { counter: number }
}
});

type MachineContext = ContextFrom<typeof machine>;

const acceptMachineContext = (_event: MachineContext) => {};

acceptMachineContext({ counter: 100 });
acceptMachineContext({
counter: 100,
// @ts-expect-error
other: 'unknown'
});
const obj = { completely: 'invalid' };
// @ts-expect-error
acceptMachineContext(obj);
});

it('should return context of a typegened machine', () => {
const machine = createMachine({
tsTypes: {} as TypegenMeta,
schema: {
context: {} as { counter: number }
}
});

type MachineContext = ContextFrom<typeof machine>;

const acceptMachineContext = (_event: MachineContext) => {};

acceptMachineContext({ counter: 100 });
acceptMachineContext({
counter: 100,
// @ts-expect-error
other: 'unknown'
});
const obj = { completely: 'invalid' };
// @ts-expect-error
acceptMachineContext(obj);
});
});

describe('EventFrom', () => {
it('should return events for a machine', () => {
const machine = createMachine({
schema: {
events: {} as
| { type: 'UPDATE_NAME'; value: string }
| { type: 'UPDATE_AGE'; value: number }
| { type: 'ANOTHER_EVENT' }
}
});

type MachineEvent = EventFrom<typeof machine>;

const acceptMachineEvent = (_event: MachineEvent) => {};

acceptMachineEvent({ type: 'UPDATE_NAME', value: 'test' });
acceptMachineEvent({ type: 'UPDATE_AGE', value: 12 });
acceptMachineEvent({ type: 'ANOTHER_EVENT' });
acceptMachineEvent({
// @ts-expect-error
type: 'UNKNOWN_EVENT'
});
});

it('should return events for a typegened machine', () => {
const machine = createMachine({
tsTypes: {} as TypegenMeta,
schema: {
events: {} as
| { type: 'UPDATE_NAME'; value: string }
| { type: 'UPDATE_AGE'; value: number }
| { type: 'ANOTHER_EVENT' }
}
});

type MachineEvent = EventFrom<typeof machine>;

const acceptMachineEvent = (_event: MachineEvent) => {};

acceptMachineEvent({ type: 'UPDATE_NAME', value: 'test' });
acceptMachineEvent({ type: 'UPDATE_AGE', value: 12 });
acceptMachineEvent({ type: 'ANOTHER_EVENT' });
acceptMachineEvent({
// @ts-expect-error
type: 'UNKNOWN_EVENT'
});
});

it('should return events for createModel', () => {
const userModel = createModel(
{},
Expand Down

0 comments on commit 3706c62

Please sign in to comment.