diff options
Diffstat (limited to 'src/utils')
| -rw-r--r-- | src/utils/adt.ts | 26 |
1 files changed, 26 insertions, 0 deletions
diff --git a/src/utils/adt.ts b/src/utils/adt.ts new file mode 100644 index 0000000..c19398b --- /dev/null +++ b/src/utils/adt.ts @@ -0,0 +1,26 @@ +type TagValue<T, N> = T extends Tag<N, infer V> ? V : never + +export const match = + <R, T extends Tag<string, any>>(pattern: { + [key in T['tag'] | '_']?: (v: TagValue<T, key>) => R + }) => + (tag: T): R => + ((pattern as any)[tag.tag] || (pattern._ as any))(tag.value) + +type Tag<N, V> = { tag: N; value: V } +export type Enum<T> = { [N in keyof T]: Tag<N, T[N]> }[keyof T] + +export const constructors = <T extends Tag<string, any>>(): { + [N in T['tag']]: TagValue<T, N> extends null | never + ? (value?: null | never) => T + : (value: TagValue<T, N>) => T +} => + new Proxy( + {}, + { + get(_, k) { + return (value: any) => ({ tag: k, value }) + }, + }, + ) as any + |
