Advertisement
Guest User

Untitled

a guest
Apr 26th, 2019
84
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 2.73 KB | None | 0 0
  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. };
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement