type TagValue = T extends Tag ? V : never export const match = >( tag: T, pattern: { [key in T['tag'] | '_']?: (v: TagValue) => R }, ): R => ((pattern as any)[tag.tag] || (pattern._ as any))(tag.value) export const matchString = ( key: T, pattern: { [key in T | '_']?: (key: key) => R }, ): R => ((pattern as any)[key] || (pattern._ as any))(key) type Tag = { tag: N; value: V } export type Enum = { [N in keyof T]: Tag }[keyof T] export const constructors = >(): { [N in T['tag']]: TagValue extends null | never ? (value?: null | never) => T : (value: TagValue) => T } => new Proxy( {}, { get(_, k) { return (value: any) => ({ tag: k, value }) }, }, ) as any