SHARE
TWEET

Untitled

a guest Apr 26th, 2019 63 Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. import { EventObject } from 'xstate';
  2.  
  3. interface StateSchema<TEvents extends EventObject, TAllStates extends string> {
  4.   states?: { [K in TAllStates]: StateNode<TEvents, TAllStates> };
  5. }
  6. interface StateNode<
  7.   TEvents extends EventObject,
  8.   TAllStates extends string,
  9.   TContext = any
  10. > extends StateSchema<TEvents, TAllStates> {
  11.   context: TContext;
  12.   transitions: Array<Transition<TEvents, TAllStates>>;
  13. }
  14. interface Transition<TEvents extends EventObject, TAllStates extends string> {
  15.   to: TAllStates;
  16.   event: TEvents;
  17. }
  18.  
  19. // I'm sorry Anders... this isn't your fault
  20. type ContextMapFromStateSchema<
  21.   TStateSchema extends StateSchema<any, any>
  22. > = TStateSchema['states'] extends Record<infer Keys, any>
  23.   ? { [K in Keys]: TStateSchema['states'][K]['context'] }
  24.   : never;
  25.  
  26. type ContextUnionFromStateSchema<
  27.   TStateSchema extends StateSchema<any, any>
  28. > = TStateSchema['states'] extends Record<any, infer TStateNode>
  29.   ? TStateNode extends { context: infer TCtx }
  30.     ? TCtx
  31.     : never
  32.   : never;
  33.  
  34. type TransitionConfig<T extends StateSchema<any, any>> = {
  35.   [K in keyof T['states']]: {
  36.     // oh god oh no
  37.     on: {
  38.       [E in T['states'][K]['transitions'][number]['event']['type']]: ActionFunction<
  39.         ContextMapFromStateSchema<T>[K],
  40.         Extract<T['states'][K]['transitions'][number]['event'], { type: E }>,
  41.         ContextMapFromStateSchema<T>[Extract<
  42.           T['states'][K]['transitions'][number],
  43.           { event: { type: E } }
  44.         >['to']]
  45.       >
  46.     };
  47.   }
  48. };
  49.  
  50. type ActionFunction<TContext, TEvent extends EventObject, TReturnContext> = (
  51.   ctx: TContext,
  52.   event: TEvent
  53. ) => TReturnContext;
  54.  
  55. export enum States {
  56.   EVEN = 'EVEN',
  57.   ODD = 'ODD',
  58. }
  59.  
  60. export enum EventTypes {
  61.   CLICK = 'CLICK',
  62.   DOUBLE_CLICK = 'DOUBLE_CLICK',
  63.   CLEAR = 'CLEAR',
  64. }
  65.  
  66. interface ClickEvent {
  67.   type: EventTypes.CLICK;
  68. }
  69.  
  70. interface DoubleClickEvent {
  71.   type: EventTypes.DOUBLE_CLICK;
  72. }
  73.  
  74. interface ExampleSchema {
  75.   states: {
  76.     [States.EVEN]: {
  77.       context: {
  78.         value: 'EVEN';
  79.       };
  80.       transitions: [
  81.         { to: States.ODD; event: ClickEvent },
  82.         { to: States.EVEN; event: DoubleClickEvent }
  83.       ];
  84.     };
  85.     [States.ODD]: {
  86.       context: {
  87.         value: 'ODD';
  88.       };
  89.       transitions: [
  90.         { to: States.EVEN; event: ClickEvent },
  91.         { to: States.ODD; event: DoubleClickEvent }
  92.       ];
  93.     };
  94.   };
  95. }
  96.  
  97. export const config: TransitionConfig<ExampleSchema> = {
  98.   [States.ODD]: {
  99.     on: {
  100.       CLICK: (_ctx /* ctx is { value: 'ODD' } */, _event) => {
  101.         return { value: 'EVE' };
  102.       },
  103.       DOUBLE_CLICK: (_ctx, _event) => {
  104.         return { value: 'ODD' };
  105.       },
  106.     },
  107.   },
  108.   [States.EVEN]: {
  109.     on: {
  110.       CLICK: (_ctx /* ctx is { value: 'EVEN' }, */, _event) => {
  111.         return { value: 'ODD' };
  112.       },
  113.     },
  114.   },
  115. };
RAW Paste Data
We use cookies for various purposes including analytics. By continuing to use Pastebin, you agree to our use of cookies as described in the Cookies Policy. OK, I Understand
Not a member of Pastebin yet?
Sign Up, it unlocks many cool features!
 
Top