ts-pattern
Version:
The exhaustive Pattern Matching library for TypeScript.
1 lines • 64.8 kB
Source Map (JSON)
{"version":3,"file":"index.cjs","sources":["../src/internals/symbols.ts","../src/internals/helpers.ts","../src/is-matching.ts","../src/patterns.ts","../src/errors.ts","../src/match.ts"],"sourcesContent":["/**\n * Symbols used internally within ts-pattern to construct and discriminate\n * Guard, Not, and Select, and AnonymousSelect patterns\n *\n * Symbols have the advantage of not appearing in auto-complete suggestions in\n * user defined patterns, and eliminate the risk of property\n * overlap between ts-pattern internals and user defined patterns.\n *\n * These symbols have to be visible to tsc for type inference to work, but\n * users should not import them\n * @module\n * @private\n * @internal\n */\n\nexport const matcher = Symbol.for('@ts-pattern/matcher');\nexport type matcher = typeof matcher;\n\nexport const unset = Symbol.for('@ts-pattern/unset');\nexport type unset = typeof unset;\n\nexport const isVariadic = Symbol.for('@ts-pattern/isVariadic');\nexport type isVariadic = typeof isVariadic;\n\n// can't be a symbol because this key has to be enumerable.\nexport const anonymousSelectKey = '@ts-pattern/anonymous-select-key';\nexport type anonymousSelectKey = typeof anonymousSelectKey;\n\nexport const override = Symbol.for('@ts-pattern/override');\nexport type override = typeof override;\n","/**\n * @module\n * @private\n * @internal\n */\n\nimport * as symbols from './symbols';\nimport { SelectionType } from '../types/FindSelected';\nimport { Pattern, Matcher, MatcherType, AnyMatcher } from '../types/Pattern';\n\n// @internal\nexport const isObject = (value: unknown): value is Object =>\n Boolean(value && typeof value === 'object');\n\n// @internal\nexport const isMatcher = (\n x: unknown\n): x is Matcher<unknown, unknown, MatcherType, SelectionType> => {\n const pattern = x as Matcher<unknown, unknown, MatcherType, SelectionType>;\n return pattern && !!pattern[symbols.matcher];\n};\n\n// @internal\nconst isOptionalPattern = (\n x: unknown\n): x is Matcher<unknown, unknown, 'optional', SelectionType> => {\n return isMatcher(x) && x[symbols.matcher]().matcherType === 'optional';\n};\n\n// tells us if the value matches a given pattern.\n// @internal\nexport const matchPattern = (\n pattern: any,\n value: any,\n select: (key: string, value: unknown) => void\n): boolean => {\n if (isMatcher(pattern)) {\n const matcher = pattern[symbols.matcher]();\n const { matched, selections } = matcher.match(value);\n if (matched && selections) {\n Object.keys(selections).forEach((key) => select(key, selections[key]));\n }\n return matched;\n }\n\n if (isObject(pattern)) {\n if (!isObject(value)) return false;\n\n // Tuple pattern\n if (Array.isArray(pattern)) {\n if (!Array.isArray(value)) return false;\n let startPatterns = [];\n let endPatterns = [];\n let variadicPatterns: AnyMatcher[] = [];\n\n for (const i of pattern.keys()) {\n const subpattern = pattern[i];\n if (isMatcher(subpattern) && subpattern[symbols.isVariadic]) {\n variadicPatterns.push(subpattern);\n } else if (variadicPatterns.length) {\n endPatterns.push(subpattern);\n } else {\n startPatterns.push(subpattern);\n }\n }\n\n if (variadicPatterns.length) {\n if (variadicPatterns.length > 1) {\n throw new Error(\n `Pattern error: Using \\`...P.array(...)\\` several times in a single pattern is not allowed.`\n );\n }\n\n if (value.length < startPatterns.length + endPatterns.length) {\n return false;\n }\n\n const startValues = value.slice(0, startPatterns.length);\n const endValues =\n endPatterns.length === 0 ? [] : value.slice(-endPatterns.length);\n const middleValues = value.slice(\n startPatterns.length,\n endPatterns.length === 0 ? Infinity : -endPatterns.length\n );\n\n return (\n startPatterns.every((subPattern, i) =>\n matchPattern(subPattern, startValues[i], select)\n ) &&\n endPatterns.every((subPattern, i) =>\n matchPattern(subPattern, endValues[i], select)\n ) &&\n (variadicPatterns.length === 0\n ? true\n : matchPattern(variadicPatterns[0], middleValues, select))\n );\n }\n\n return pattern.length === value.length\n ? pattern.every((subPattern, i) =>\n matchPattern(subPattern, value[i], select)\n )\n : false;\n }\n\n return Reflect.ownKeys(pattern).every((k): boolean => {\n const subPattern = pattern[k];\n\n return (\n (k in value || isOptionalPattern(subPattern)) &&\n matchPattern(subPattern, value[k], select)\n );\n });\n }\n\n return Object.is(value, pattern);\n};\n\n// @internal\nexport const getSelectionKeys = (pattern: any): string[] => {\n if (isObject(pattern)) {\n if (isMatcher(pattern)) {\n return pattern[symbols.matcher]().getSelectionKeys?.() ?? [];\n }\n if (Array.isArray(pattern)) return flatMap(pattern, getSelectionKeys);\n return flatMap(Object.values(pattern), getSelectionKeys);\n }\n return [];\n};\n\n// @internal\nexport const flatMap = <a, b>(\n xs: readonly a[],\n f: (v: a) => readonly b[]\n): b[] => xs.reduce<b[]>((acc, x) => acc.concat(f(x)), []);\n","import { MatchedValue, Pattern, UnknownProperties } from './types/Pattern';\nimport * as P from './patterns';\nimport { matchPattern } from './internals/helpers';\nimport { WithDefault } from './types/helpers';\n\n/**\n * This constraint allows using additional properties\n * in object patterns. See \"should allow targetting unknown properties\"\n * unit test in `is-matching.test.ts`.\n */\ntype PatternConstraint<T> = T extends readonly any[]\n ? P.Pattern<T>\n : T extends object\n ? P.Pattern<T> & UnknownProperties\n : P.Pattern<T>;\n\n/**\n * `isMatching` takes pattern and returns a **type guard** function, cheching if a value matches this pattern.\n *\n * [Read documentation for `isMatching` on GitHub](https://github.com/gvergnaud/ts-pattern#ismatching)\n *\n * @example\n * const hasName = isMatching({ name: P.string })\n *\n * declare let input: unknown\n *\n * if (hasName(input)) {\n * // `input` inferred as { name: string }\n * return input.name\n * }\n */\nexport function isMatching<const p extends Pattern<unknown>>(\n pattern: p\n): (value: unknown) => value is P.infer<p>;\n/**\n * `isMatching` takes pattern and a value and checks if the value matches this pattern.\n *\n * [Read documentation for `isMatching` on GitHub](https://github.com/gvergnaud/ts-pattern#ismatching)\n *\n * @example\n * declare let input: unknown\n *\n * if (isMatching({ name: P.string }, input)) {\n * // `input` inferred as { name: string }\n * return input.name\n * }\n */\nexport function isMatching<const T, const P extends PatternConstraint<T>>(\n pattern: P,\n value: T\n): value is T & WithDefault<P.narrow<T, P>, P.infer<P>>;\n\nexport function isMatching<const p extends Pattern<any>>(\n ...args: [pattern: p, value?: any]\n): boolean | ((vale: any) => boolean) {\n if (args.length === 1) {\n const [pattern] = args;\n return (value: any): value is MatchedValue<any, P.infer<p>> =>\n matchPattern(pattern, value, () => {});\n }\n if (args.length === 2) {\n const [pattern, value] = args;\n return matchPattern(pattern, value, () => {});\n }\n\n throw new Error(\n `isMatching wasn't given the right number of arguments: expected 1 or 2, received ${args.length}.`\n );\n}\n","/**\n * The `P` module contains patterns for primitive types, wildcards and\n * other pattern-matching utilities.\n *\n * @module\n */\n\nimport { matchPattern, getSelectionKeys, flatMap } from './internals/helpers';\nimport * as symbols from './internals/symbols';\nimport { matcher } from './internals/symbols';\nimport { isMatching } from './is-matching';\nimport { ExtractPreciseValue } from './types/ExtractPreciseValue';\nimport { Fn } from './types/helpers';\nimport { InvertPattern } from './types/InvertPattern';\nimport {\n Pattern,\n UnknownPattern,\n OptionalP,\n ArrayP,\n MapP,\n SetP,\n AndP,\n OrP,\n NotP,\n GuardP,\n SelectP,\n AnonymousSelectP,\n GuardExcludeP,\n CustomP,\n Matcher,\n StringPattern,\n AnyPattern,\n NumberPattern,\n BooleanPattern,\n BigIntPattern,\n NullishPattern,\n SymbolPattern,\n Chainable,\n BigIntChainable,\n NumberChainable,\n StringChainable,\n ArrayChainable,\n Variadic,\n NonNullablePattern,\n} from './types/Pattern';\n\nexport type {\n /**\n * `Pattern<T>` is the type of all patterns\n * that can match a value of type `T`.\n */\n Pattern,\n\n /**\n * `unstable_Fn` can be used to created a\n * a Matchable instance – a custom type that\n * can be used as a pattern.\n *\n * @experimental This feature is unstable.\n */\n Fn as unstable_Fn,\n};\n\nexport { matcher };\n\n/**\n * A `Matchable` is an object implementing\n * the Matcher Protocol. It must have a `[P.matcher]: P.Matcher<NarrowFn>`\n * key, which defines how this object should be matched by TS-Pattern.\n *\n * @experimental This feature is unstable.\n *\n * @example\n * ```ts\n * class Some<T> implements P.unstable_Matchable {\n * [P.matcher](): P.unstable_Matcher<Some<T>>\n * }\n * ```\n */\nexport type unstable_Matchable<\n narrowedOrFn,\n input = unknown,\n pattern = never\n> = CustomP<input, pattern, narrowedOrFn>;\n\n/**\n * A `Matcher` is an object with `match` function, which\n * defines how this object should be matched by TS-Pattern.\n *\n * @experimental This feature is unstable.\n *\n * @example\n * ```ts\n * class Some<T> implements P.unstable_Matchable {\n * [P.matcher](): P.unstable_Matcher<Some<T>>\n * }\n * ```\n */\nexport type unstable_Matcher<\n narrowedOrFn,\n input = unknown,\n pattern = never\n> = ReturnType<CustomP<input, pattern, narrowedOrFn>[matcher]>;\n\n/**\n * `P.infer<typeof somePattern>` will return the type of the value\n * matched by this pattern.\n *\n * [Read the documentation for `P.infer` on GitHub](https://github.com/gvergnaud/ts-pattern#pinfer)\n *\n * @example\n * const userPattern = { name: P.string }\n * type User = P.infer<typeof userPattern>\n */\nexport type infer<pattern> = InvertPattern<NoInfer<pattern>, unknown>;\n\n/**\n * `P.narrow<Input, Pattern>` will narrow the input type to only keep\n * the set of values that are compatible with the provided pattern type.\n *\n * [Read the documentation for `P.narrow` on GitHub](https://github.com/gvergnaud/ts-pattern#pnarrow)\n *\n * @example\n * type Input = ['a' | 'b' | 'c', 'a' | 'b' | 'c']\n * const Pattern = ['a', P.union('a', 'b')] as const\n *\n * type Narrowed = P.narrow<Input, typeof Pattern>\n * // ^? ['a', 'a' | 'b']\n */\nexport type narrow<input, pattern> = ExtractPreciseValue<\n input,\n InvertPattern<pattern, input>\n>;\n\nfunction chainable<pattern extends Matcher<any, any, any, any, any>>(\n pattern: pattern\n): Chainable<pattern> {\n return Object.assign(pattern, {\n optional: () => optional(pattern),\n and: (p2: any) => intersection(pattern, p2),\n or: (p2: any) => union(pattern, p2),\n select: (key: any) =>\n key === undefined ? select(pattern) : select(key, pattern),\n }) as Chainable<pattern>;\n}\n\nconst variadic = <pattern extends {}>(pattern: pattern): Variadic<pattern> =>\n Object.assign(pattern, {\n [Symbol.iterator](): Iterator<pattern, void, undefined> {\n let i = 0;\n const variadicPattern = Object.assign(pattern, {\n [symbols.isVariadic]: true,\n });\n const values: IteratorResult<pattern, void>[] = [\n { value: variadicPattern, done: false },\n { done: true, value: undefined },\n ];\n return {\n next: () => values[i++] ?? values.at(-1)!,\n };\n },\n });\n\nfunction arrayChainable<pattern extends Matcher<any, any, any, any, any>>(\n pattern: pattern\n): ArrayChainable<pattern> {\n return Object.assign(variadic(pattern), {\n optional: () => arrayChainable(optional(pattern)),\n select: (key: any) =>\n arrayChainable(\n key === undefined ? select(pattern) : select(key, pattern)\n ),\n }) as any;\n}\n\n/**\n * `P.optional(subpattern)` takes a sub pattern and returns a pattern which matches if the\n * key is undefined or if it is defined and the sub pattern matches its value.\n *\n * [Read the documentation for `P.optional` on GitHub](https://github.com/gvergnaud/ts-pattern#poptional-patterns)\n *\n * @example\n * match(value)\n * .with({ greeting: P.optional('Hello') }, () => 'will match { greeting?: \"Hello\" }')\n */\nexport function optional<\n input,\n const pattern extends unknown extends input ? UnknownPattern : Pattern<input>\n>(pattern: pattern): Chainable<OptionalP<input, pattern>, 'optional'> {\n return chainable({\n [matcher]() {\n return {\n match: <UnknownInput>(value: UnknownInput | input) => {\n let selections: Record<string, unknown[]> = {};\n const selector = (key: string, value: any) => {\n selections[key] = value;\n };\n if (value === undefined) {\n getSelectionKeys(pattern).forEach((key) =>\n selector(key, undefined)\n );\n return { matched: true, selections };\n }\n const matched = matchPattern(pattern, value, selector);\n return { matched, selections };\n },\n getSelectionKeys: () => getSelectionKeys(pattern),\n matcherType: 'optional',\n };\n },\n });\n}\n\ntype UnwrapArray<xs> = xs extends readonly (infer x)[] ? x : never;\n\ntype UnwrapSet<xs> = xs extends Set<infer x> ? x : never;\n\ntype UnwrapMapKey<xs> = xs extends Map<infer k, any> ? k : never;\n\ntype UnwrapMapValue<xs> = xs extends Map<any, infer v> ? v : never;\n\ntype WithDefault<a, b> = [a] extends [never] ? b : a;\n\n/**\n * `P.array(subpattern)` takes a sub pattern and returns a pattern, which matches\n * arrays if all their elements match the sub pattern.\n *\n * [Read the documentation for `P.array` on GitHub](https://github.com/gvergnaud/ts-pattern#parray-patterns)\n *\n * @example\n * match(value)\n * .with({ users: P.array({ name: P.string }) }, () => 'will match { name: string }[]')\n */\nexport function array<input>(): ArrayChainable<ArrayP<input, unknown>>;\nexport function array<\n input,\n const pattern extends Pattern<WithDefault<UnwrapArray<input>, unknown>>\n>(pattern: pattern): ArrayChainable<ArrayP<input, pattern>>;\nexport function array(\n ...args: [pattern?: any]\n): ArrayChainable<ArrayP<any, any>> {\n return arrayChainable({\n [matcher]() {\n return {\n match: (value: any) => {\n if (!Array.isArray(value)) return { matched: false };\n\n if (args.length === 0) return { matched: true };\n\n const pattern = args[0];\n let selections: Record<string, unknown[]> = {};\n\n if (value.length === 0) {\n getSelectionKeys(pattern).forEach((key) => {\n selections[key] = [];\n });\n return { matched: true, selections };\n }\n\n const selector = (key: string, value: unknown) => {\n selections[key] = (selections[key] || []).concat([value]);\n };\n\n const matched = value.every((v) =>\n matchPattern(pattern, v, selector)\n );\n\n return { matched, selections };\n },\n getSelectionKeys: () =>\n args.length === 0 ? [] : getSelectionKeys(args[0]),\n };\n },\n });\n}\n\n/**\n * `P.set(subpattern)` takes a sub pattern and returns a pattern that matches\n * sets if all their elements match the sub pattern.\n *\n * [Read `P.set` documentation on GitHub](https://github.com/gvergnaud/ts-pattern#pset-patterns)\n *\n * @example\n * match(value)\n * .with({ users: P.set(P.string) }, () => 'will match Set<string>')\n */\nexport function set<input>(): Chainable<SetP<input, unknown>>;\nexport function set<\n input,\n const pattern extends Pattern<WithDefault<UnwrapSet<input>, unknown>>\n>(pattern: pattern): Chainable<SetP<input, pattern>>;\nexport function set<\n input,\n const pattern extends Pattern<WithDefault<UnwrapSet<input>, unknown>>\n>(...args: [pattern?: pattern]): Chainable<SetP<input, pattern>> {\n return chainable({\n [matcher]() {\n return {\n match: <UnknownInput>(value: UnknownInput | input) => {\n if (!(value instanceof Set)) return { matched: false };\n\n let selections: Record<string, unknown[]> = {};\n\n if (value.size === 0) {\n return { matched: true, selections };\n }\n\n if (args.length === 0) return { matched: true };\n\n const selector = (key: string, value: unknown) => {\n selections[key] = (selections[key] || []).concat([value]);\n };\n\n const pattern = args[0];\n\n const matched = setEvery(value, (v) =>\n matchPattern(pattern, v, selector)\n );\n\n return { matched, selections };\n },\n getSelectionKeys: () =>\n args.length === 0 ? [] : getSelectionKeys(args[0]),\n };\n },\n });\n}\n\nconst setEvery = <T>(set: Set<T>, predicate: (value: T) => boolean) => {\n for (const value of set) {\n if (predicate(value)) continue;\n return false;\n }\n return true;\n};\n\n/**\n * `P.map(keyPattern, valuePattern)` takes a subpattern to match against the\n * key, a subpattern to match against the value and returns a pattern that\n * matches on maps where all elements inside the map match those two\n * subpatterns.\n *\n * [Read `P.map` documentation on GitHub](https://github.com/gvergnaud/ts-pattern#pmap-patterns)\n *\n * @example\n * match(value)\n * .with({ users: P.map(P.map(P.string, P.number)) }, (map) => `map's type is Map<string, number>`)\n */\nexport function map<input>(): Chainable<MapP<input, unknown, unknown>>;\nexport function map<\n input,\n const pkey extends Pattern<WithDefault<UnwrapMapKey<input>, unknown>>,\n const pvalue extends Pattern<WithDefault<UnwrapMapValue<input>, unknown>>\n>(patternKey: pkey, patternValue: pvalue): Chainable<MapP<input, pkey, pvalue>>;\nexport function map<\n input,\n const pkey extends Pattern<WithDefault<UnwrapMapKey<input>, unknown>>,\n const pvalue extends Pattern<WithDefault<UnwrapMapValue<input>, unknown>>\n>(\n ...args: [patternKey?: pkey, patternValue?: pvalue]\n): Chainable<MapP<input, pkey, pvalue>> {\n return chainable({\n [matcher]() {\n return {\n match: <UnknownInput>(value: UnknownInput | input) => {\n if (!(value instanceof Map)) return { matched: false };\n\n let selections: Record<string, unknown[]> = {};\n\n if (value.size === 0) {\n return { matched: true, selections };\n }\n\n const selector = (key: string, value: unknown) => {\n selections[key] = (selections[key] || []).concat([value]);\n };\n\n if (args.length === 0) return { matched: true };\n if (args.length === 1) {\n throw new Error(\n `\\`P.map\\` wasn\\'t given enough arguments. Expected (key, value), received ${args[0]?.toString()}`\n );\n }\n const [patternKey, patternValue] = args;\n\n const matched = mapEvery(value, (v, k) => {\n const keyMatch = matchPattern(patternKey, k, selector);\n const valueMatch = matchPattern(patternValue, v, selector);\n return keyMatch && valueMatch;\n });\n\n return { matched, selections };\n },\n getSelectionKeys: () =>\n args.length === 0\n ? []\n : [...getSelectionKeys(args[0]), ...getSelectionKeys(args[1])],\n };\n },\n });\n}\n\nconst mapEvery = <K, T>(\n map: Map<K, T>,\n predicate: (value: T, key: K) => boolean\n) => {\n for (const [key, value] of map.entries()) {\n if (predicate(value, key)) continue;\n return false;\n }\n return true;\n};\n\n/**\n * `P.intersection(...patterns)` returns a pattern which matches\n * only if **every** patterns provided in parameter match the input.\n *\n * [Read the documentation for `P.intersection` on GitHub](https://github.com/gvergnaud/ts-pattern#pintersection-patterns)\n *\n * @example\n * match(value)\n * .with(\n * {\n * user: P.intersection(\n * { firstname: P.string },\n * { lastname: P.string },\n * { age: P.when(age => age > 21) }\n * )\n * },\n * ({ user }) => 'will match { firstname: string, lastname: string, age: number } if age > 21'\n * )\n */\nexport function intersection<\n input,\n const patterns extends readonly [Pattern<input>, ...Pattern<input>[]]\n>(...patterns: patterns): Chainable<AndP<input, patterns>> {\n return chainable({\n [matcher]: () => ({\n match: (value) => {\n let selections: Record<string, unknown[]> = {};\n const selector = (key: string, value: any) => {\n selections[key] = value;\n };\n const matched = (patterns as readonly UnknownPattern[]).every((p) =>\n matchPattern(p, value, selector)\n );\n return { matched, selections };\n },\n getSelectionKeys: () =>\n flatMap(patterns as readonly UnknownPattern[], getSelectionKeys),\n matcherType: 'and',\n }),\n });\n}\n\n/**\n * `P.union(...patterns)` returns a pattern which matches\n * if **at least one** of the patterns provided in parameter match the input.\n *\n * [Read the documentation for `P.union` on GitHub](https://github.com/gvergnaud/ts-pattern#punion-patterns)\n *\n * @example\n * match(value)\n * .with(\n * { type: P.union('a', 'b', 'c') },\n * ({ type }) => 'will match { type: \"a\" | \"b\" | \"c\" }'\n * )\n */\nexport function union<\n input,\n const patterns extends readonly [Pattern<input>, ...Pattern<input>[]]\n>(...patterns: patterns): Chainable<OrP<input, patterns>> {\n return chainable({\n [matcher]: () => ({\n match: <UnknownInput>(value: UnknownInput | input) => {\n let selections: Record<string, unknown[]> = {};\n const selector = (key: string, value: any) => {\n selections[key] = value;\n };\n flatMap(\n patterns as readonly UnknownPattern[],\n getSelectionKeys\n ).forEach((key) => selector(key, undefined));\n const matched = (patterns as readonly UnknownPattern[]).some((p) =>\n matchPattern(p, value, selector)\n );\n return { matched, selections };\n },\n getSelectionKeys: () =>\n flatMap(patterns as readonly UnknownPattern[], getSelectionKeys),\n matcherType: 'or',\n }),\n });\n}\n\n/**\n * `P.not(pattern)` returns a pattern which matches if the sub pattern\n * doesn't match.\n *\n * [Read the documentation for `P.not` on GitHub](https://github.com/gvergnaud/ts-pattern#pnot-patterns)\n *\n * @example\n * match<{ a: string | number }>(value)\n * .with({ a: P.not(P.string) }, (x) => 'will match { a: number }'\n * )\n */\n\nexport function not<\n input,\n const pattern extends Pattern<input> | UnknownPattern\n>(pattern: pattern): Chainable<NotP<input, pattern>> {\n return chainable({\n [matcher]: () => ({\n match: <UnknownInput>(value: UnknownInput | input) => ({\n matched: !matchPattern(pattern, value, () => {}),\n }),\n getSelectionKeys: () => [],\n matcherType: 'not',\n }),\n });\n}\n\n/**\n * `P.when((value) => boolean)` returns a pattern which matches\n * if the predicate returns true for the current input.\n *\n * [Read the documentation for `P.when` on GitHub](https://github.com/gvergnaud/ts-pattern#pwhen-patterns)\n *\n * @example\n * match<{ age: number }>(value)\n * .with({ age: P.when(age => age > 21) }, (x) => 'will match if value.age > 21'\n * )\n */\nexport function when<input, predicate extends (value: input) => unknown>(\n predicate: predicate\n): GuardP<\n input,\n predicate extends (value: any) => value is infer narrowed ? narrowed : never\n>;\nexport function when<input, narrowed extends input, excluded>(\n predicate: (input: input) => input is narrowed\n): GuardExcludeP<input, narrowed, excluded>;\nexport function when<input, predicate extends (value: input) => unknown>(\n predicate: predicate\n): GuardP<\n input,\n predicate extends (value: any) => value is infer narrowed ? narrowed : never\n> {\n return {\n [matcher]: () => ({\n match: <UnknownInput>(value: UnknownInput | input) => ({\n matched: Boolean(predicate(value as input)),\n }),\n }),\n };\n}\n\n/**\n * `P.select()` is a pattern which will always match,\n * and will inject the selected piece of input in the handler function.\n *\n * [Read the documentation for `P.select` on GitHub](https://github.com/gvergnaud/ts-pattern#pselect-patterns)\n *\n * @example\n * match<{ age: number }>(value)\n * .with({ age: P.select() }, (age) => 'age: number'\n * )\n */\nexport function select(): Chainable<AnonymousSelectP, 'select' | 'or' | 'and'>;\nexport function select<\n input,\n const patternOrKey extends\n | string\n | (unknown extends input ? UnknownPattern : Pattern<input>)\n>(\n patternOrKey: patternOrKey\n): patternOrKey extends string\n ? Chainable<SelectP<patternOrKey, 'select' | 'or' | 'and'>>\n : Chainable<\n SelectP<symbols.anonymousSelectKey, input, patternOrKey>,\n 'select' | 'or' | 'and'\n >;\nexport function select<\n input,\n const pattern extends unknown extends input ? UnknownPattern : Pattern<input>,\n const k extends string\n>(\n key: k,\n pattern: pattern\n): Chainable<SelectP<k, input, pattern>, 'select' | 'or' | 'and'>;\nexport function select(\n ...args: [keyOrPattern?: unknown | string, pattern?: unknown]\n): Chainable<SelectP<string>, 'select' | 'or' | 'and'> {\n const key: string | undefined =\n typeof args[0] === 'string' ? args[0] : undefined;\n const pattern: unknown =\n args.length === 2\n ? args[1]\n : typeof args[0] === 'string'\n ? undefined\n : args[0];\n return chainable({\n [matcher]() {\n return {\n match: (value) => {\n let selections: Record<string, unknown> = {\n [key ?? symbols.anonymousSelectKey]: value,\n };\n const selector = (key: string, value: any) => {\n selections[key] = value;\n };\n return {\n matched:\n pattern === undefined\n ? true\n : matchPattern(pattern, value, selector),\n selections: selections,\n };\n },\n getSelectionKeys: () =>\n [key ?? symbols.anonymousSelectKey].concat(\n pattern === undefined ? [] : getSelectionKeys(pattern)\n ),\n };\n },\n });\n}\n\nfunction isUnknown(x: unknown): x is unknown {\n return true;\n}\n\nfunction isNumber<T>(x: T | number): x is number {\n return typeof x === 'number';\n}\n\nfunction isString<T>(x: T | string): x is string {\n return typeof x === 'string';\n}\n\nfunction isBoolean<T>(x: T | boolean): x is boolean {\n return typeof x === 'boolean';\n}\n\nfunction isBigInt<T>(x: T | bigint): x is bigint {\n return typeof x === 'bigint';\n}\n\nfunction isSymbol<T>(x: T | symbol): x is symbol {\n return typeof x === 'symbol';\n}\n\nfunction isNullish<T>(x: T | null | undefined): x is null | undefined {\n return x === null || x === undefined;\n}\n\nfunction isNonNullable(x: unknown): x is {} {\n return x !== null && x !== undefined;\n}\n\ntype AnyConstructor = abstract new (...args: any[]) => any;\n\nfunction isInstanceOf<T extends AnyConstructor>(classConstructor: T) {\n return (val: unknown): val is InstanceType<T> =>\n val instanceof classConstructor;\n}\n\n/**\n * `P.any` is a wildcard pattern, matching **any value**.\n *\n * [Read the documentation for `P.any` on GitHub](https://github.com/gvergnaud/ts-pattern#p_-wildcard)\n *\n * @example\n * match(value)\n * .with(P.any, () => 'will always match')\n */\nexport const any: AnyPattern = chainable(when(isUnknown));\n\n/**\n * `P._` is a wildcard pattern, matching **any value**.\n * It's an alias to `P.any`.\n *\n * [Read the documentation for `P._` on GitHub](https://github.com/gvergnaud/ts-pattern#p_-wildcard)\n *\n * @example\n * match(value)\n * .with(P._, () => 'will always match')\n */\nexport const _ = any;\n\n/**\n * `P.string.startsWith(start)` is a pattern, matching **strings** starting with `start`.\n *\n * [Read the documentation for `P.string.startsWith` on GitHub](https://github.com/gvergnaud/ts-pattern#pstringstartsWith)\n *\n * @example\n * match(value)\n * .with(P.string.startsWith('A'), () => 'value starts with an A')\n */\n\nconst startsWith = <input, const start extends string>(\n start: start\n): GuardP<input, `${start}${string}`> =>\n when((value) => isString(value) && value.startsWith(start));\n\n/**\n * `P.string.endsWith(end)` is a pattern, matching **strings** ending with `end`.\n *\n * [Read the documentation for `P.string.endsWith` on GitHub](https://github.com/gvergnaud/ts-pattern#pstringendsWith)\n *\n * @example\n * match(value)\n * .with(P.string.endsWith('!'), () => 'value ends with an !')\n */\nconst endsWith = <input, const end extends string>(\n end: end\n): GuardP<input, `${string}${end}`> =>\n when((value) => isString(value) && value.endsWith(end));\n\n/**\n * `P.string.minLength(min)` is a pattern, matching **strings** with at least `min` characters.\n *\n * [Read the documentation for `P.string.minLength` on GitHub](https://github.com/gvergnaud/ts-pattern#pstringminLength)\n *\n * @example\n * match(value)\n * .with(P.string.minLength(10), () => 'string with more length >= 10')\n */\nconst minLength = <const min extends number>(min: min) =>\n when((value) => isString(value) && value.length >= min);\n\n/**\n * `P.string.length(len)` is a pattern, matching **strings** with exactly `len` characters.\n *\n * [Read the documentation for `P.string.length` on GitHub](https://github.com/gvergnaud/ts-pattern#pstringlength)\n *\n * @example\n * match(value)\n * .with(P.string.length(10), () => 'strings with length === 10')\n */\nconst length = <const len extends number>(len: len) =>\n when((value) => isString(value) && value.length === len);\n\n/**\n * `P.string.maxLength(max)` is a pattern, matching **strings** with at most `max` characters.\n *\n * [Read the documentation for `P.string.maxLength` on GitHub](https://github.com/gvergnaud/ts-pattern#pstringmaxLength)\n *\n * @example\n * match(value)\n * .with(P.string.maxLength(10), () => 'string with more length <= 10')\n */\nconst maxLength = <const max extends number>(max: max) =>\n when((value) => isString(value) && value.length <= max);\n\n/**\n * `P.string.includes(substr)` is a pattern, matching **strings** containing `substr`.\n *\n * [Read the documentation for `P.string.includes` on GitHub](https://github.com/gvergnaud/ts-pattern#pstringincludes)\n *\n * @example\n * match(value)\n * .with(P.string.includes('http'), () => 'value contains http')\n */\nconst includes = <input, const substr extends string>(\n substr: substr\n): GuardExcludeP<input, string, never> =>\n when((value) => isString(value) && value.includes(substr));\n\n/**\n * `P.string.regex(expr)` is a pattern, matching **strings** that `expr` regular expression.\n *\n * [Read the documentation for `P.string.regex` on GitHub](https://github.com/gvergnaud/ts-pattern#pstringregex)\n *\n * @example\n * match(value)\n * .with(P.string.regex(/^https?:\\/\\//), () => 'url')\n */\nconst regex = <input, const expr extends string | RegExp>(\n expr: expr\n): GuardExcludeP<input, string, never> =>\n when((value) => isString(value) && Boolean(value.match(expr)));\n\nconst stringChainable = <pattern extends Matcher<any, any, any, any, any>>(\n pattern: pattern\n): StringChainable<pattern> =>\n Object.assign(chainable(pattern), {\n startsWith: (str: string) =>\n stringChainable(intersection(pattern, startsWith(str))),\n endsWith: (str: string) =>\n stringChainable(intersection(pattern, endsWith(str))),\n minLength: (min: number) =>\n stringChainable(intersection(pattern, minLength(min))),\n length: (len: number) =>\n stringChainable(intersection(pattern, length(len))),\n maxLength: (max: number) =>\n stringChainable(intersection(pattern, maxLength(max))),\n includes: (str: string) =>\n stringChainable(intersection(pattern, includes(str))),\n regex: (str: string) => stringChainable(intersection(pattern, regex(str))),\n }) as any;\n\n/**\n * `P.string` is a wildcard pattern, matching any **string**.\n *\n * [Read the documentation for `P.string` on GitHub](https://github.com/gvergnaud/ts-pattern#pstring-wildcard)\n *\n * @example\n * match(value)\n * .with(P.string, () => 'will match on strings')\n */\nexport const string: StringPattern = stringChainable(when(isString));\n\n/**\n * `P.number.between(min, max)` matches **numbers** between `min` and `max`,\n * equal to min or equal to max.\n *\n * [Read the documentation for `P.number.between` on GitHub](https://github.com/gvergnaud/ts-pattern#pnumberbetween)\n *\n * @example\n * match(value)\n * .with(P.number.between(0, 10), () => '0 <= numbers <= 10')\n */\nconst between = <input, const min extends number, const max extends number>(\n min: min,\n max: max\n): GuardExcludeP<input, number, never> =>\n when((value) => isNumber(value) && min <= value && max >= value);\n\n/**\n * `P.number.lt(max)` matches **numbers** smaller than `max`.\n *\n * [Read the documentation for `P.number.lt` on GitHub](https://github.com/gvergnaud/ts-pattern#pnumberlt)\n *\n * @example\n * match(value)\n * .with(P.number.lt(10), () => 'numbers < 10')\n */\nconst lt = <input, const max extends number>(\n max: max\n): GuardExcludeP<input, number, never> =>\n when((value) => isNumber(value) && value < max);\n\n/**\n * `P.number.gt(min)` matches **numbers** greater than `min`.\n *\n * [Read the documentation for `P.number.gt` on GitHub](https://github.com/gvergnaud/ts-pattern#pnumbergt)\n *\n * @example\n * match(value)\n * .with(P.number.gt(10), () => 'numbers > 10')\n */\nconst gt = <input, const min extends number>(\n min: min\n): GuardExcludeP<input, number, never> =>\n when((value) => isNumber(value) && value > min);\n\n/**\n * `P.number.lte(max)` matches **numbers** smaller than or equal to `max`.\n *\n * [Read the documentation for `P.number.lte` on GitHub](https://github.com/gvergnaud/ts-pattern#pnumberlte)\n *\n * @example\n * match(value)\n * .with(P.number.lte(10), () => 'numbers <= 10')\n */\nconst lte = <input, const max extends number>(\n max: max\n): GuardExcludeP<input, number, never> =>\n when((value) => isNumber(value) && value <= max);\n\n/**\n * `P.number.gte(min)` matches **numbers** greater than or equal to `min`.\n *\n * [Read the documentation for `P.number.gte` on GitHub](https://github.com/gvergnaud/ts-pattern#pnumbergte)\n *\n * @example\n * match(value)\n * .with(P.number.gte(10), () => 'numbers >= 10')\n */\nconst gte = <input, const min extends number>(\n min: min\n): GuardExcludeP<input, number, never> =>\n when((value) => isNumber(value) && value >= min);\n\n/**\n * `P.number.int()` matches **integer** numbers.\n *\n * [Read the documentation for `P.number.int()` on GitHub](https://github.com/gvergnaud/ts-pattern#pnumberint)\n *\n * @example\n * match(value)\n * .with(P.number.int(), () => 'an integer')\n */\nconst int = <input>(): GuardExcludeP<input, number, never> =>\n when((value) => isNumber(value) && Number.isInteger(value));\n\n/**\n * `P.number.finite` matches **finite numbers**.\n *\n * [Read the documentation for `P.number.finite` on GitHub](https://github.com/gvergnaud/ts-pattern#pnumberfinite)\n *\n * @example\n * match(value)\n * .with(P.number.finite, () => 'not Infinity')\n */\nconst finite = <input>(): GuardExcludeP<input, number, never> =>\n when((value) => isNumber(value) && Number.isFinite(value));\n\n/**\n * `P.number.positive()` matches **positive** numbers.\n *\n * [Read the documentation for `P.number.positive()` on GitHub](https://github.com/gvergnaud/ts-pattern#pnumberpositive)\n *\n * @example\n * match(value)\n * .with(P.number.positive(), () => 'number > 0')\n */\nconst positive = <input>(): GuardExcludeP<input, number, never> =>\n when((value) => isNumber(value) && value > 0);\n\n/**\n * `P.number.negative()` matches **negative** numbers.\n *\n * [Read the documentation for `P.number.negative()` on GitHub](https://github.com/gvergnaud/ts-pattern#pnumbernegative)\n *\n * @example\n * match(value)\n * .with(P.number.negative(), () => 'number < 0')\n */\nconst negative = <input>(): GuardExcludeP<input, number, never> =>\n when((value) => isNumber(value) && value < 0);\n\nconst numberChainable = <pattern extends Matcher<any, any, any, any, any>>(\n pattern: pattern\n): NumberChainable<pattern> =>\n Object.assign(chainable(pattern), {\n between: (min: number, max: number) =>\n numberChainable(intersection(pattern, between(min, max))),\n lt: (max: number) => numberChainable(intersection(pattern, lt(max))),\n gt: (min: number) => numberChainable(intersection(pattern, gt(min))),\n lte: (max: number) => numberChainable(intersection(pattern, lte(max))),\n gte: (min: number) => numberChainable(intersection(pattern, gte(min))),\n int: () => numberChainable(intersection(pattern, int())),\n finite: () => numberChainable(intersection(pattern, finite())),\n positive: () => numberChainable(intersection(pattern, positive())),\n negative: () => numberChainable(intersection(pattern, negative())),\n }) as any;\n\n/**\n * `P.number` is a wildcard pattern, matching any **number**.\n *\n * [Read the documentation for `P.number` on GitHub](https://github.com/gvergnaud/ts-pattern#pnumber-wildcard)\n *\n * @example\n * match(value)\n * .with(P.number, () => 'will match on numbers')\n */\nexport const number: NumberPattern = numberChainable(when(isNumber));\n\n/**\n * `P.bigint.between(min, max)` matches **bigint** between `min` and `max`,\n * equal to min or equal to max.\n *\n * [Read the documentation for `P.bigint.between` on GitHub](https://github.com/gvergnaud/ts-pattern#pnumberbetween)\n *\n * @example\n * match(value)\n * .with(P.bigint.between(0, 10), () => '0 <= bigints <= 10')\n */\nconst betweenBigInt = <\n input,\n const min extends bigint,\n const max extends bigint\n>(\n min: min,\n max: max\n): GuardExcludeP<input, bigint, never> =>\n when((value) => isBigInt(value) && min <= value && max >= value);\n\n/**\n * `P.bigint.lt(max)` matches **bigint** smaller than `max`.\n *\n * [Read the documentation for `P.bigint.lt` on GitHub](https://github.com/gvergnaud/ts-pattern#pnumberlt)\n *\n * @example\n * match(value)\n * .with(P.bigint.lt(10), () => 'bigints < 10')\n */\nconst ltBigInt = <input, const max extends bigint>(\n max: max\n): GuardExcludeP<input, bigint, never> =>\n when((value) => isBigInt(value) && value < max);\n\n/**\n * `P.bigint.gt(min)` matches **bigint** greater than `min`.\n *\n * [Read the documentation for `P.bigint.gt` on GitHub](https://github.com/gvergnaud/ts-pattern#pnumbergt)\n *\n * @example\n * match(value)\n * .with(P.bigint.gt(10), () => 'bigints > 10')\n */\nconst gtBigInt = <input, const min extends bigint>(\n min: min\n): GuardExcludeP<input, bigint, never> =>\n when((value) => isBigInt(value) && value > min);\n\n/**\n * `P.bigint.lte(max)` matches **bigint** smaller than or equal to `max`.\n *\n * [Read the documentation for `P.bigint.lte` on GitHub](https://github.com/gvergnaud/ts-pattern#pnumberlte)\n *\n * @example\n * match(value)\n * .with(P.bigint.lte(10), () => 'bigints <= 10')\n */\nconst lteBigInt = <input, const max extends bigint>(\n max: max\n): GuardExcludeP<input, bigint, never> =>\n when((value) => isBigInt(value) && value <= max);\n\n/**\n * `P.bigint.gte(min)` matches **bigint** greater than or equal to `min`.\n *\n * [Read the documentation for `P.bigint.gte` on GitHub](https://github.com/gvergnaud/ts-pattern#pbigintgte)\n *\n * @example\n * match(value)\n * .with(P.bigint.gte(10), () => 'bigints >= 10')\n */\nconst gteBigInt = <input, const min extends bigint>(\n min: min\n): GuardExcludeP<input, bigint, never> =>\n when((value) => isBigInt(value) && value >= min);\n\n/**\n * `P.bigint.positive()` matches **positive** bigints.\n *\n * [Read the documentation for `P.bigint.positive()` on GitHub](https://github.com/gvergnaud/ts-pattern#pbigintpositive)\n *\n * @example\n * match(value)\n * .with(P.bigint.positive(), () => 'bigint > 0')\n */\nconst positiveBigInt = <input>(): GuardExcludeP<input, bigint, never> =>\n when((value) => isBigInt(value) && value > 0);\n\n/**\n * `P.bigint.negative()` matches **negative** bigints.\n *\n * [Read the documentation for `P.bigint.negative()` on GitHub](https://github.com/gvergnaud/ts-pattern#pbigintnegative)\n *\n * @example\n * match(value)\n * .with(P.bigint.negative(), () => 'bigint < 0')\n */\nconst negativeBigInt = <input>(): GuardExcludeP<input, bigint, never> =>\n when((value) => isBigInt(value) && value < 0);\n\nconst bigintChainable = <pattern extends Matcher<any, any, any, any, any>>(\n pattern: pattern\n): BigIntChainable<pattern> =>\n Object.assign(chainable(pattern), {\n between: (min: bigint, max: bigint) =>\n bigintChainable(intersection(pattern, betweenBigInt(min, max))),\n lt: (max: bigint) => bigintChainable(intersection(pattern, ltBigInt(max))),\n gt: (min: bigint) => bigintChainable(intersection(pattern, gtBigInt(min))),\n lte: (max: bigint) =>\n bigintChainable(intersection(pattern, lteBigInt(max))),\n gte: (min: bigint) =>\n bigintChainable(intersection(pattern, gteBigInt(min))),\n positive: () => bigintChainable(intersection(pattern, positiveBigInt())),\n negative: () => bigintChainable(intersection(pattern, negativeBigInt())),\n }) as any;\n\n/**\n * `P.bigint` is a wildcard pattern, matching any **bigint**.\n *\n * [Read the documentation for `P.bigint` on GitHub](https://github.com/gvergnaud/ts-pattern#number-wildcard)\n *\n * @example\n * .with(P.bigint, () => 'will match on bigints')\n */\nexport const bigint: BigIntPattern = bigintChainable(when(isBigInt));\n\n/**\n * `P.boolean` is a wildcard pattern, matching any **boolean**.\n *\n * [Read the documentation for `P.boolean` on GitHub](https://github.com/gvergnaud/ts-pattern#boolean-wildcard)\n *\n * @example\n * .with(P.boolean, () => 'will match on booleans')\n */\nexport const boolean: BooleanPattern = chainable(when(isBoolean));\n\n/**\n * `P.symbol` is a wildcard pattern, matching any **symbol**.\n *\n * [Read the documentation for `P.symbol` on GitHub](https://github.com/gvergnaud/ts-pattern#symbol-wildcard)\n *\n * @example\n * .with(P.symbol, () => 'will match on symbols')\n */\nexport const symbol: SymbolPattern = chainable(when(isSymbol));\n\n/**\n * `P.nullish` is a wildcard pattern, matching **null** or **undefined**.\n *\n * [Read the documentation for `P.nullish` on GitHub](https://github.com/gvergnaud/ts-pattern#nullish-wildcard)\n *\n * @example\n * .with(P.nullish, (x) => `${x} is null or undefined`)\n */\nexport const nullish: NullishPattern = chainable(when(isNullish));\n\n/**\n * `P.nonNullable` is a wildcard pattern, matching everything except **null** or **undefined**.\n *\n * [Read the documentation for `P.nonNullable` on GitHub](https://github.com/gvergnaud/ts-pattern#nonNullable-wildcard)\n *\n * @example\n * .with(P.nonNullable, (x) => `${x} isn't null nor undefined`)\n */\nexport const nonNullable: NonNullablePattern = chainable(when(isNonNullable));\n\n/**\n * `P.instanceOf(SomeClass)` is a pattern matching instances of a given class.\n *\n * [Read the documentation for `P.instanceOf` on GitHub](https://github.com/gvergnaud/ts-pattern#pinstanceof-patterns)\n *\n * @example\n * .with(P.instanceOf(SomeClass), () => 'will match on SomeClass instances')\n */\nexport function instanceOf<T extends AnyConstructor>(\n classConstructor: T\n): Chainable<GuardP<unknown, InstanceType<T>>> {\n return chainable(when(isInstanceOf(classConstructor)));\n}\n\n/**\n * `P.shape(somePattern)` lets you call methods like `.optional()`, `.and`, `.or` and `.select()`\n * On structural patterns, like objects and arrays.\n *\n * [Read the documentation for `P.shape` on GitHub](https://github.com/gvergnaud/ts-pattern#pshape-patterns)\n *\n * @example\n * .with(\n * {\n * state: P.shape({ status: \"success\" }).optional().select()\n * },\n * (state) => 'match the success state, or undefined.'\n * )\n */\nexport function shape<input, const pattern extends Pattern<input>>(\n pattern: pattern\n): Chainable<GuardP<input, InvertPattern<pattern, input>>>;\nexport function shape(pattern: UnknownPattern) {\n return chainable(when(isMatching(pattern)));\n}\n","/**\n * Error when the given input value does not match any included pattern\n * and .exhaustive() was specified\n */\nexport class NonExhaustiveError extends Error {\n constructor(public input: unknown) {\n let displayedValue;\n try {\n displayedValue = JSON.stringify(input);\n } catch (e) {\n displayedValue = input;\n }\n super(`Pattern matching error: no pattern matches value ${displayedValue}`);\n }\n}\n","import { Pattern } from './types/Pattern';\nimport { Match } from './types/Match';\nimport * as symbols from './internals/symbols';\nimport { matchPattern } from './internals/helpers';\nimport { NonExhaustiveError } from './errors';\n\ntype MatchState<output> =\n | { matched: true; value: output }\n | { matched: false; value: undefined };\n\nconst unmatched: MatchState<never> = {\n matched: false,\n value: undefined,\n};\n\n/**\n * `match` creates a **pattern matching expression**.\n * * Use `.with(pattern, handler)` to pattern match on the input.\n * * Use `.exhaustive()` or `.otherwise(() => defaultValue)` to end the expression and get the result.\n *\n * [Read the documentation for `match` on GitHub](https://github.com/gvergnaud/ts-pattern#match)\n *\n * @example\n * declare let input: \"A\" | \"B\";\n *\n * return match(input)\n * .with(\"A\", () => \"It's an A!\")\n * .with(\"B\", () => \"It's a B!\")\n * .exhaustive();\n *\n */\nexport function match<const input, output = symbols.unset>(\n value: input\n): Match<input, output> {\n return new MatchExpression(value, unmatched) as any;\n}\n\n/**\n * This class represents a match expression. It follows the\n * builder pattern, we chain methods to add features to the expression\n * until we call `.exhaustive`, `.otherwise` or the unsafe `.run`\n * method to execute it.\n *\n * The types of this class aren't public, the public type definition\n * can be found in src/types/Match.ts.\n */\nclass MatchExpression<input, output> {\n constructor(private input: input, private state: MatchState<output>) {}\n\n with(...args: any[]): MatchExpression<input, output> {\n if (this.state.matched) return this;\n\n const handler: (selection: unknown, value: input) => output =\n args[args.length - 1];\n\n const patterns: Pattern<input>[] = [args[0]];\n let predicate: ((value: input) => unknown) | undefined = undefined;\n\n if (args.length === 3 && typeof args[1] === 'function') {\n // case with guard as second argument\n predicate = args[1];\n } else if (args.length > 2) {\n // case with several patterns\n patterns.push(...args.slice(1, args.length - 1));\n }\n\n let hasSelections = false;\n let selected: Record<string, unknown> = {};\n const select = (key: string, value: unknown) => {\n hasSelections = true;\n selected[key] = value;\n };\n\n const matched =\n patterns.some((pattern) => matchPattern(pattern, this.input, select)) &&\n (predicate ? Boolean(predicate(this.input)) : true);\n\n const selections = hasSelections\n ? symbols.anonymousSelectKey in selected\n ? selected[symbols.anonymousSelectKey]\n : selected\n : this.input;\n\n const state = matched\n ? {\n matched: true as const,\n value: handler(selections, this.input),\n }\n : unmatched;\n\n return new MatchExpression(this.input, state);\n }\n\n when(\n predicate: (value: input) => unknown,\n handler: (selection: input, value: input) => output\n ): MatchExpression<input, output> {\n if (this.state.matched) return this;\n\n const matched = Boolean(predicate(this.input));\n\n return new MatchExpression<input, output>(\n this.input,\n matched\n ? { matched: true, value: handler(this.input, this.input) }\n : unmatched\n );\n }\n\n otherwise(handler: (value: input) => output): output {\n if (this.state.matched) return this.state.value;\n return handler(this.input);\n }\n\n exhaustive(unexpectedValueHandler = defaultCatcher): output {\n if (this.state.matched) return this.state.value;\n return unexpectedValueHandler(this.input);\n }\n\n run(): output {\n return this.exhaustive();\n }\n\n returnType() {\n return this;\n }\n}\n\nfunction defaultCatcher(input: unknown): never {\n throw new NonExhaustiveError(input);\n}\n"],"names":["matcher","Symbol","isVariadic","anonymousSelectKey","isObject","value","Boolean","isMatcher","x","symbols","matchPattern","pattern","select","_matcher$match","match","matched","selections","Object","keys","forEach","key","Array","isArray","_step","startPatterns","endPatterns","variadicPatterns","_iterator","_createForOfIteratorHelperLoose","done","subpatte