Advertisement
Guest User

Untitled

a guest
Oct 19th, 2019
148
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 1.77 KB | None | 0 0
  1. export type UnionType = {kind: string};
  2.  
  3. export type UnionMemberByKind<U, K> = Extract<U, { kind: K }>
  4.  
  5. export type UnionMatchObj<U extends UnionType, Ret> = {
  6. [K in U['kind']]: (unionMember: UnionMemberByKind<U, K>) => Ret
  7. };
  8.  
  9. export type Merge<M extends {}, N extends {}> = {
  10. [P in Exclude<keyof M, keyof N>]: M[P]
  11. } & N;
  12.  
  13. export const match = <U extends UnionType, RetT>(
  14. fObj: UnionMatchObj<U, RetT>
  15. ) => (
  16. unionVal: U
  17. ) => (
  18. fObj[unionVal.kind as U['kind']](unionVal as any)
  19. );
  20.  
  21. export const matcher =
  22. <U extends UnionType>() =>
  23. <RetT>(fObj: UnionMatchObj<U, RetT>) => (
  24. match<U, RetT>(fObj)
  25. );
  26.  
  27. type PartialBy<T, K extends keyof T> = Omit<T, K> & Partial<Pick<T, K>>
  28.  
  29. export const makeFactory = <T extends UnionType>(kind: T['kind']) =>
  30. (init: PartialBy<T, 'kind'>): T => ({
  31. ...init,
  32. kind
  33. } as T);
  34.  
  35. /* ///////////////////////////////////// */
  36. // For example...
  37. /* ///////////////////////////////////// */
  38.  
  39. type Move = {
  40. kind: 'move';
  41. direction: string;
  42. player: string;
  43. };
  44.  
  45. type Attack = {
  46. kind: 'attack';
  47. target: string;
  48. player: string;
  49. };
  50.  
  51. type LeaveDungeon = {
  52. kind: 'leaveDungeon';
  53. player: string;
  54. };
  55.  
  56. type DungeonEvent = Move | Attack | LeaveDungeon;
  57.  
  58. const Move = makeFactory<Move>('move');
  59. const Attack = makeFactory<Attack>('attack');
  60. const LeaveDungeon = makeFactory<LeaveDungeon>('leaveDungeon');
  61.  
  62. const toString = match<DungeonEvent, string>({
  63. move: ({direction, player}) => `${player} moving ${direction}`,
  64. attack: ({target, player}) => `${player} is attacking ${target}`,
  65. leaveDungeon: ({player}) => `${player} has left the dungeon`
  66. });
  67.  
  68. const newEvent = Move({direction: 'east', player: 'Zardul'});
  69.  
  70. console.log(toString(newEvent));
  71.  
  72. const secondEvent = LeaveDungeon({player: 'Zardul'});
  73.  
  74. console.log(toString(secondEvent));
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement