deno.land / x / xstate@xstate@4.33.6 / test / typeHelpers.test.ts
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407import { assign, ContextFrom, createMachine, EmittedFrom, EventFrom, interpret, MachineOptionsFrom, StateValueFrom} 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 an interpreter', () => { const machine = createMachine({ schema: { events: {} as | { type: 'UPDATE_NAME'; value: string } | { type: 'UPDATE_AGE'; value: number } | { type: 'ANOTHER_EVENT' } } });
const service = interpret(machine);
type InterpreterEvent = EventFrom<typeof service>;
const acceptInterpreterEvent = (_event: InterpreterEvent) => {};
acceptInterpreterEvent({ type: 'UPDATE_NAME', value: 'test' }); acceptInterpreterEvent({ type: 'UPDATE_AGE', value: 12 }); acceptInterpreterEvent({ type: 'ANOTHER_EVENT' }); acceptInterpreterEvent({ // @ts-expect-error type: 'UNKNOWN_EVENT' }); });
it('should return events for createModel', () => { const userModel = createModel( {}, { events: { updateName: (value: string) => ({ value }), updateAge: (value: number) => ({ value }), anotherEvent: () => ({}) } } );
type UserModelEvent = EventFrom<typeof userModel>;
const acceptUserModelEvent = (_event: UserModelEvent) => {};
acceptUserModelEvent({ type: 'updateName', value: 'test' }); acceptUserModelEvent({ type: 'updateAge', value: 12 }); acceptUserModelEvent({ type: 'anotherEvent' }); acceptUserModelEvent({ // @ts-expect-error type: 'eventThatDoesNotExist' }); });
it('should narrow events down to the specified types', () => { const userModel = createModel( {}, { events: { updateName: (value: string) => ({ value }), updateAge: (value: number) => ({ value }), anotherEvent: () => ({}) } } );
type UserModelEventSubset = EventFrom< typeof userModel, 'updateName' | 'updateAge' >;
const acceptUserModelEventSubset = ( _userModelEventSubset: UserModelEventSubset ) => {};
acceptUserModelEventSubset({ type: 'updateName', value: 'test' }); acceptUserModelEventSubset({ type: 'updateAge', value: 12 }); // @ts-expect-error acceptUserModelEventSubset({ type: 'anotherEvent' }); // @ts-expect-error acceptUserModelEventSubset({ type: 'eventThatDoesNotExist' }); });
it('should correctly extract events from events having union of strings as their `type`', () => { const machine = createMachine({ schema: { events: {} as { type: 'INC' | 'DEC' } } });
type MachineEvent = EventFrom<typeof machine, 'INC'>;
const acceptEvent = (_event: MachineEvent) => {};
acceptEvent({ type: 'INC' }); });});
describe('MachineOptionsFrom', () => { it('should return options for a typegen-less machine', () => { const machine = createMachine({ context: { count: 100 }, schema: { events: {} as { type: 'FOO' } | { type: 'BAR'; value: string } } });
const acceptMachineOptions = ( _options: MachineOptionsFrom<typeof machine> ) => {};
acceptMachineOptions({ actions: { foo: () => {} } }); acceptMachineOptions({ actions: { foo: assign(() => ({})) } }); acceptMachineOptions({ actions: { foo: assign((ctx) => { ((_accept: number) => {})(ctx.count); return {}; }) } }); acceptMachineOptions({ actions: { foo: assign((_ctx, ev) => { ((_accept: 'FOO' | 'BAR') => {})(ev.type); return {}; }) } }); // @ts-expect-error acceptMachineOptions(100); });
it('should return optional options for a typegen-based machine by default', () => { interface TypesMeta extends TypegenMeta { missingImplementations: { actions: 'myAction'; delays: never; guards: never; services: never; }; eventsCausingActions: { myAction: 'FOO'; }; } const machine = createMachine({ tsTypes: {} as TypesMeta, context: { count: 100 }, schema: { events: {} as { type: 'FOO' } | { type: 'BAR'; value: string } } });
const acceptMachineOptions = ( _options: MachineOptionsFrom<typeof machine> ) => {};
acceptMachineOptions({ actions: { // @ts-expect-error foo: () => {} } }); acceptMachineOptions({ actions: {} }); acceptMachineOptions({ actions: { myAction: assign((ctx, ev) => { ((_accept: number) => {})(ctx.count); ((_accept: 'FOO') => {})(ev.type); return {}; }) } }); // @ts-expect-error acceptMachineOptions(100); });
it('should return required options for a typegen-based machine with a flag', () => { interface TypesMeta extends TypegenMeta { missingImplementations: { actions: 'myAction'; delays: never; guards: never; services: never; }; eventsCausingActions: { myAction: 'FOO'; }; } const machine = createMachine({ tsTypes: {} as TypesMeta, context: { count: 100 }, schema: { events: {} as { type: 'FOO' } | { type: 'BAR'; value: string } } });
const acceptMachineOptions = ( _options: MachineOptionsFrom<typeof machine, true> ) => {};
acceptMachineOptions({ actions: { // @ts-expect-error foo: () => {} } }); acceptMachineOptions({ // @ts-expect-error actions: {} }); acceptMachineOptions({ actions: { myAction: assign((ctx, ev) => { ((_accept: number) => {})(ctx.count); ((_accept: 'FOO') => {})(ev.type); return {}; }) } }); // @ts-expect-error acceptMachineOptions(100); });});
describe('StateValueFrom', () => { it('should return possible state values from a typegened machine', () => { interface TypesMeta extends TypegenMeta { matchesStates: 'a' | 'b' | 'c'; }
const machine = createMachine({ tsTypes: {} as TypesMeta });
function matches(_value: StateValueFrom<typeof machine>) {}
matches('a'); matches('b'); // @ts-expect-error matches('unknown'); });
it('should return any from a typegenless machine', () => { const machine = createMachine({});
function matches(_value: StateValueFrom<typeof machine>) {}
matches('just anything'); });});
describe('EmittedFrom', () => { it('should return state type from a service that has concrete event type', () => { const service = interpret( createMachine({ schema: { events: {} as { type: 'FOO' } } }) );
function acceptState(_state: EmittedFrom<typeof service>) {}
acceptState(service.initialState); // @ts-expect-error acceptState("isn't any"); });
it('should return state from a service created based on a model without any concrete events', () => { const service = interpret( createModel( {}, { // this empty obj is important for this test case } ).createMachine({}) );
function acceptState(_state: EmittedFrom<typeof service>) {}
acceptState(service.initialState); // @ts-expect-error acceptState("isn't any"); });});
Version Info