Created
December 2, 2024 11:55
-
-
Save izakfilmalter/6745ef53a0fd865e7dc2c423e66cb71d to your computer and use it in GitHub Desktop.
Match
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| export type ADTMember<ADT, Key extends string, Type extends string> = Extract< | |
| ADT, | |
| /* eslint-disable @typescript-eslint/consistent-indexed-object-style */ | |
| { [k in Key]: Type } | |
| > | |
| type Matchers<Key extends string, ADT extends { [k in Key]: string }, Out> = { | |
| [D in ADT[Key]]: (v: ADTMember<ADT, Key, D>) => Out | |
| } | |
| export const matchOn = | |
| <K extends string>(key: K) => | |
| <ADT extends { [k in K]: string }, Z>(matchObj: Matchers<K, ADT, Z>) => | |
| (v: ADT) => | |
| matchObj[v[key]](v as ADTMember<ADT, K, (typeof v)[K]>) | |
| export const matchOnI = | |
| <K extends string>(key: K) => | |
| <ADT extends { [k in K]: string }>(v: ADT) => | |
| <Z>(matchObj: Matchers<K, ADT, Z>) => | |
| matchObj[v[key]](v as ADTMember<ADT, K, (typeof v)[K]>) | |
| /** | |
| * Pattern matcher for matching over tagged unions whose discriminant value is "tag" | |
| * @example | |
| * ```ts | |
| * export type TicketDetail = | |
| | { | |
| tag: 'tracking' | |
| } | |
| | { | |
| tag: 'info' | |
| contents: TicketInfoRequest | |
| } | |
| | { | |
| tag: 'change' | |
| contents: TicketChangeRequest | |
| } | |
| declare const detail: TicketDetail | |
| pipe(detail, | |
| match({ | |
| tracking: () => "I'm super tracked!", | |
| info: i => i.contents.status, | |
| change: c => c.contents.justification | |
| })) | |
| * ``` | |
| */ | |
| export const match = matchOn('tag') | |
| export const matchType = matchOn('type') | |
| /** | |
| * Like {@link match} but inverted argument order | |
| * @example | |
| * ```ts | |
| * export type TicketDetail = | |
| | { | |
| tag: 'tracking' | |
| } | |
| | { | |
| tag: 'info' | |
| contents: TicketInfoRequest | |
| } | |
| | { | |
| tag: 'change' | |
| contents: TicketChangeRequest | |
| } | |
| declare const detail: TicketDetail | |
| matchI(detail)({ | |
| tracking: () => "I'm super tracked!", | |
| info: i => i.contents.status, | |
| change: c => c.contents.justification | |
| }) | |
| * ``` | |
| */ | |
| export const matchI = matchOnI('tag') | |
| export const matchS = | |
| <S extends string>(s: S) => | |
| <Out>(matchObj: { [M in S]: () => Out }): Out => | |
| matchObj[s]() |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment