diff --git a/.changeset/good-queens-cross.md b/.changeset/good-queens-cross.md new file mode 100644 index 0000000000..bdaaadd72a --- /dev/null +++ b/.changeset/good-queens-cross.md @@ -0,0 +1,5 @@ +--- +'xstate': patch +--- + +Fixed `ContextFrom` helper type to work on typegened machines. diff --git a/.changeset/wet-insects-share.md b/.changeset/wet-insects-share.md new file mode 100644 index 0000000000..b077c3a18b --- /dev/null +++ b/.changeset/wet-insects-share.md @@ -0,0 +1,5 @@ +--- +'xstate': patch +--- + +Fixed `EventFrom` helper type to work on machines. diff --git a/packages/core/src/types.ts b/packages/core/src/types.ts index ccb0b7c959..525b89002b 100644 --- a/packages/core/src/types.ts +++ b/packages/core/src/types.ts @@ -1783,13 +1783,27 @@ export type EmittedFrom = ReturnTypeOrValue extends infer R : never; type ResolveEventType = ReturnTypeOrValue extends infer R - ? R extends StateMachine + ? R extends StateMachine< + infer _, + infer __, + infer TEvent, + infer ___, + infer ____, + infer _____, + infer ______ + > ? TEvent - : R extends Model + : R extends Model ? TEvent - : R extends State + : R extends State ? TEvent - : R extends Interpreter + : R extends Interpreter< + infer _, + infer __, + infer TEvent, + infer ___, + infer ____ + > ? TEvent : R extends ActorRef ? TEvent @@ -1803,13 +1817,27 @@ export type EventFrom< > = IsNever extends true ? TEvent : Extract; export type ContextFrom = ReturnTypeOrValue extends infer R - ? R extends StateMachine + ? R extends StateMachine< + infer TContext, + infer _, + infer __, + infer ___, + infer ____, + infer _____, + infer ______ + > ? TContext : R extends Model ? TContext - : R extends State + : R extends State ? TContext - : R extends Interpreter + : R extends Interpreter< + infer TContext, + infer _, + infer __, + infer ___, + infer ____ + > ? TContext : never : never; diff --git a/packages/core/test/typeHelpers.test.ts b/packages/core/test/typeHelpers.test.ts index d82f829b9a..7d14031830 100644 --- a/packages/core/test/typeHelpers.test.ts +++ b/packages/core/test/typeHelpers.test.ts @@ -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; + + 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; + + 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; + + 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; + + 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( {},