Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- export type UnionType = {kind: string};
- export type UnionMemberByKind<U, K> = Extract<U, { kind: K }>
- export type UnionMatchObj<U extends UnionType, Ret> = {
- [K in U['kind']]: (unionMember: UnionMemberByKind<U, K>) => Ret
- };
- export type Merge<M extends {}, N extends {}> = {
- [P in Exclude<keyof M, keyof N>]: M[P]
- } & N;
- export const match = <U extends UnionType, RetT>(
- fObj: UnionMatchObj<U, RetT>
- ) => (
- unionVal: U
- ) => (
- fObj[unionVal.kind as U['kind']](unionVal as any)
- );
- export const matcher =
- <U extends UnionType>() =>
- <RetT>(fObj: UnionMatchObj<U, RetT>) => (
- match<U, RetT>(fObj)
- );
- type PartialBy<T, K extends keyof T> = Omit<T, K> & Partial<Pick<T, K>>
- export const makeFactory = <T extends UnionType>(kind: T['kind']) =>
- (init: PartialBy<T, 'kind'>): T => ({
- ...init,
- kind
- } as T);
- /* ///////////////////////////////////// */
- // For example...
- /* ///////////////////////////////////// */
- type Move = {
- kind: 'move';
- direction: string;
- player: string;
- };
- type Attack = {
- kind: 'attack';
- target: string;
- player: string;
- };
- type LeaveDungeon = {
- kind: 'leaveDungeon';
- player: string;
- };
- type DungeonEvent = Move | Attack | LeaveDungeon;
- const Move = makeFactory<Move>('move');
- const Attack = makeFactory<Attack>('attack');
- const LeaveDungeon = makeFactory<LeaveDungeon>('leaveDungeon');
- const toString = match<DungeonEvent, string>({
- move: ({direction, player}) => `${player} moving ${direction}`,
- attack: ({target, player}) => `${player} is attacking ${target}`,
- leaveDungeon: ({player}) => `${player} has left the dungeon`
- });
- const newEvent = Move({direction: 'east', player: 'Zardul'});
- console.log(toString(newEvent));
- const secondEvent = LeaveDungeon({player: 'Zardul'});
- console.log(toString(secondEvent));
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement