export const eq = (a: T) => (b: T): boolean => a === b type TagValue = T extends Tag ? V : never; export const match = > (pattern: { [key in T['tag'] | '_']?: (v: TagValue) => R }) => (tag: T): R => (pattern[tag.tag] || pattern._ as any)(tag.value) type Tag = { tag: N; value: V } export type Union = { [N in keyof T]: Tag }[keyof T] export const constructors = >(): { [N in keyof T]: (value: T[N]) => Union // Tag } => new Proxy( {}, { get(_, k) { return (value: any) => ({ tag: k, value }) }, }, ) as any export const jlog = (x: any) => console.log(JSON.stringify(x, null, 2))