ts-pattern
Advanced tools
Comparing version 3.3.4 to 4.0.0-rc.0
@@ -1,35 +0,6 @@ | ||
import type { Pattern } from './types/Pattern'; | ||
import type { Match, MatchedValue } from './types/Match'; | ||
import { when, not, select, instanceOf } from './guards'; | ||
import { __ } from './wildcards'; | ||
import { InvertPattern } from './types/InvertPattern'; | ||
/** | ||
* # Pattern matching | ||
**/ | ||
export { Pattern, __, when, not, select, instanceOf }; | ||
/** | ||
* #### match | ||
* | ||
* Entry point to create a pattern matching expression. | ||
* | ||
* It returns a `Match` builder, on which you can chain | ||
* several `.with(pattern, handler)` clauses. | ||
*/ | ||
export declare const match: <i, o = "@ts-pattern/unset">(value: i) => Match<i, o, never, never>; | ||
/** | ||
* Helper function taking a pattern and returning a **type guard** function telling | ||
* us whether or not a value matches the pattern. | ||
* | ||
* @param pattern the Pattern the value should match | ||
* @returns a function taking the value and returning whether or not it matches the pattern. | ||
*/ | ||
export declare function isMatching<p extends Pattern<any>>(pattern: p): (value: any) => value is MatchedValue<any, InvertPattern<p>>; | ||
/** | ||
* **type guard** function taking a pattern and a value and returning a boolean telling | ||
* us whether or not the value matches the pattern. | ||
* | ||
* @param pattern the Pattern the value should match | ||
* @param value | ||
* @returns a boolean telling whether or not the value matches the pattern. | ||
*/ | ||
export declare function isMatching<p extends Pattern<any>>(pattern: p, value: any): value is MatchedValue<any, InvertPattern<p>>; | ||
import * as P from './patterns'; | ||
export type { Pattern } from './types/Pattern'; | ||
export { select, when, not, instanceOf, __ } from './patterns'; | ||
export { match } from './match'; | ||
export { isMatching } from './is-matching'; | ||
export { P }; |
423
lib/index.js
@@ -1,13 +0,305 @@ | ||
"use strict"; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
exports.isMatching = exports.match = exports.instanceOf = exports.select = exports.not = exports.when = exports.__ = void 0; | ||
const symbols = require("./symbols"); | ||
const guards_1 = require("./guards"); | ||
Object.defineProperty(exports, "when", { enumerable: true, get: function () { return guards_1.when; } }); | ||
Object.defineProperty(exports, "not", { enumerable: true, get: function () { return guards_1.not; } }); | ||
Object.defineProperty(exports, "select", { enumerable: true, get: function () { return guards_1.select; } }); | ||
Object.defineProperty(exports, "instanceOf", { enumerable: true, get: function () { return guards_1.instanceOf; } }); | ||
const wildcards_1 = require("./wildcards"); | ||
Object.defineProperty(exports, "__", { enumerable: true, get: function () { return wildcards_1.__; } }); | ||
/** | ||
* @license | ||
* author: Gabriel Vergnaud | ||
* TSPattern.js v4.0.0-rc.0 | ||
* Released under the MIT license. | ||
*/ | ||
'use strict'; | ||
Object.defineProperty(exports, '__esModule', { value: true }); | ||
/** | ||
* Symbols used internally within ts-pattern to construct and discriminate | ||
* Guard, Not, and Select, and AnonymousSelect patterns | ||
* | ||
* Symbols have the advantage of not appearing in auto-complete suggestions in | ||
* user defined patterns, and eliminate the risk of property | ||
* overlap between ts-pattern internals and user defined patterns. | ||
* | ||
* These symbols have to be visible to tsc for type inference to work, but | ||
* users should not import them | ||
* @module | ||
* @private | ||
* @internal | ||
*/ | ||
const matcher = Symbol('@ts-pattern/matcher'); | ||
const anonymousSelectKey = '@ts-pattern/anonymous-select-key'; | ||
// @internal | ||
const isObject = (value) => Boolean(value && typeof value === 'object'); | ||
// @internal | ||
const isMatchable = (x) => { | ||
const pattern = x; | ||
return pattern && !!pattern[matcher]; | ||
}; | ||
// @internal | ||
const isOptionalPattern = (x) => { | ||
return isMatchable(x) && x[matcher]().matcherType === 'optional'; | ||
}; | ||
// tells us if the value matches a given pattern. | ||
// @internal | ||
const matchPattern = (pattern, value, select) => { | ||
if (isObject(pattern)) { | ||
if (isMatchable(pattern)) { | ||
const matcher$1 = pattern[matcher](); | ||
const { matched, selections = {} } = matcher$1.match(value); | ||
if (matched) { | ||
Object.keys(selections).forEach((key) => select(key, selections[key])); | ||
} | ||
return matched; | ||
} | ||
if (!isObject(value)) | ||
return false; | ||
if (Array.isArray(pattern)) { | ||
if (!Array.isArray(value)) | ||
return false; | ||
// Tuple pattern | ||
return pattern.length === value.length | ||
? pattern.every((subPattern, i) => matchPattern(subPattern, value[i], select)) | ||
: false; | ||
} | ||
if (pattern instanceof Map) { | ||
if (!(value instanceof Map)) | ||
return false; | ||
return Array.from(pattern.keys()).every((key) => matchPattern(pattern.get(key), value.get(key), select)); | ||
} | ||
if (pattern instanceof Set) { | ||
if (!(value instanceof Set)) | ||
return false; | ||
if (pattern.size === 0) | ||
return value.size === 0; | ||
if (pattern.size === 1) { | ||
const [subPattern] = Array.from(pattern.values()); | ||
return isMatchable(subPattern) | ||
? Array.from(value.values()).every((v) => matchPattern(subPattern, v, select)) | ||
: value.has(subPattern); | ||
} | ||
return Array.from(pattern.values()).every((subPattern) => value.has(subPattern)); | ||
} | ||
return Object.keys(pattern).every((k) => { | ||
// @ts-ignore | ||
const subPattern = pattern[k]; | ||
return ((k in value || isOptionalPattern(subPattern)) && | ||
matchPattern(subPattern, | ||
// @ts-ignore | ||
value[k], select)); | ||
}); | ||
} | ||
return Object.is(value, pattern); | ||
}; | ||
const getSelectionKeys = (pattern) => { | ||
if (isObject(pattern)) { | ||
if (isMatchable(pattern)) { | ||
return pattern[matcher]().getSelectionKeys?.() ?? []; | ||
} | ||
if (Array.isArray(pattern)) | ||
return flatMap(pattern, getSelectionKeys); | ||
return flatMap(Object.values(pattern), getSelectionKeys); | ||
} | ||
return []; | ||
}; | ||
// @internal | ||
const flatMap = (xs, f) => xs.reduce((acc, p) => acc.concat(f(p)), []); | ||
const optional = (pattern) => { | ||
return { | ||
[matcher]() { | ||
return { | ||
match: (value) => { | ||
let selections = {}; | ||
const selector = (key, value) => { | ||
selections[key] = value; | ||
}; | ||
if (value === undefined) { | ||
getSelectionKeys(pattern).forEach((key) => selector(key, undefined)); | ||
return { matched: true, selections }; | ||
} | ||
const matched = matchPattern(pattern, value, selector); | ||
return { matched, selections }; | ||
}, | ||
getSelectionKeys: () => getSelectionKeys(pattern), | ||
matcherType: 'optional', | ||
}; | ||
}, | ||
}; | ||
}; | ||
const array = (pattern) => { | ||
return { | ||
[matcher]() { | ||
return { | ||
match: (value) => { | ||
if (!Array.isArray(value)) | ||
return { matched: false }; | ||
let selections = {}; | ||
const selector = (key, value) => { | ||
selections[key] = (selections[key] || []).concat([value]); | ||
}; | ||
const matched = value.every((v) => matchPattern(pattern, v, selector)); | ||
return { matched, selections }; | ||
}, | ||
getSelectionKeys: () => getSelectionKeys(pattern), | ||
}; | ||
}, | ||
}; | ||
}; | ||
const intersection = (...patterns) => ({ | ||
[matcher]: () => ({ | ||
match: (value) => { | ||
let selections = {}; | ||
const selector = (key, value) => { | ||
selections[key] = value; | ||
}; | ||
const matched = patterns.every((p) => matchPattern(p, value, selector)); | ||
return { matched, selections }; | ||
}, | ||
getSelectionKeys: () => patterns.reduce((acc, p) => acc.concat(getSelectionKeys(p)), []), | ||
matcherType: 'and', | ||
}), | ||
}); | ||
const union = (...patterns) => ({ | ||
[matcher]: () => ({ | ||
match: (value) => { | ||
let selections = {}; | ||
const selector = (key, value) => { | ||
selections[key] = value; | ||
}; | ||
flatMap(patterns, getSelectionKeys).forEach((key) => selector(key, undefined)); | ||
const matched = patterns.some((p) => matchPattern(p, value, selector)); | ||
return { matched, selections }; | ||
}, | ||
getSelectionKeys: () => patterns.reduce((acc, p) => acc.concat(getSelectionKeys(p)), []), | ||
matcherType: 'or', | ||
}), | ||
}); | ||
const not = (pattern) => ({ | ||
[matcher]: () => ({ | ||
match: (value) => ({ matched: !matchPattern(pattern, value, () => { }) }), | ||
getSelectionKeys: () => [], | ||
matcherType: 'not', | ||
}), | ||
}); | ||
const when = (predicate) => ({ | ||
[matcher]: () => ({ | ||
match: (value) => ({ matched: predicate(value) }), | ||
}), | ||
}); | ||
function select(key) { | ||
return { | ||
[matcher]() { | ||
return { | ||
match: (value) => ({ | ||
matched: true, | ||
selections: { [key ?? anonymousSelectKey]: value }, | ||
}), | ||
getSelectionKeys: () => [key ?? anonymousSelectKey], | ||
}; | ||
}, | ||
}; | ||
} | ||
function isUnknown(x) { | ||
return true; | ||
} | ||
function isNumber(x) { | ||
return typeof x === 'number'; | ||
} | ||
function isString(x) { | ||
return typeof x === 'string'; | ||
} | ||
function isBoolean(x) { | ||
return typeof x === 'boolean'; | ||
} | ||
function isBigInt(x) { | ||
return typeof x === 'bigint'; | ||
} | ||
function isSymbol(x) { | ||
return typeof x === 'symbol'; | ||
} | ||
function isNullish(x) { | ||
return x === null || x === undefined; | ||
} | ||
function isInstanceOf(classConstructor) { | ||
return (val) => val instanceof classConstructor; | ||
} | ||
/** | ||
* ### Catch All wildcard | ||
* `__` is a wildcard pattern, matching **any value**. | ||
* @example | ||
* match(value) | ||
* .with(__, () => 'will always match') | ||
*/ | ||
const __ = when(isUnknown); | ||
/** | ||
* ### String wildcard | ||
* `P.string` is a wildcard pattern matching any **string**. | ||
* @example | ||
* match(value) | ||
* .with(P.string, () => 'will match on strings only') | ||
*/ | ||
const string = when(isString); | ||
/** | ||
* ### Number wildcard | ||
* `P.number` is a wildcard pattern matching any **number**. | ||
* @example | ||
* match(value) | ||
* .with(P.number, () => 'will match on numbers only') | ||
*/ | ||
const number = when(isNumber); | ||
/** | ||
* ### Boolean wildcard | ||
* `P.boolean` is a wildcard pattern matching any **boolean**. | ||
* @example | ||
* .with(P.boolean, () => 'will match on booleans only') | ||
*/ | ||
const boolean = when(isBoolean); | ||
/** | ||
* ### BigInt wildcard | ||
* `P.bigint` is a wildcard pattern matching any **bigint**. | ||
* @example | ||
* .with(P.bigint, () => 'will match on bigints only') | ||
*/ | ||
const bigint = when(isBigInt); | ||
/** | ||
* ### Symbol wildcard | ||
* `P.symbol` is a wildcard pattern matching any **symbol**. | ||
* @example | ||
* .with(P.symbol, () => 'will match on symbols only') | ||
*/ | ||
const symbol = when(isSymbol); | ||
/** | ||
* ### Nullish wildcard | ||
* `P.nullish` is a wildcard pattern matching **null** or **undefined**. | ||
* @example | ||
* .with(P.nullish, () => 'will match on null or undefined only') | ||
*/ | ||
const nullish = when(isNullish); | ||
/** | ||
* ### instanceOf | ||
* `P.instanceOf(SomeClass)` is a pattern matching instances of a given class. | ||
* @example | ||
* .with(P.instanceOf(SomeClass), () => 'will match on SomeClass instances') | ||
*/ | ||
const instanceOf = (classConstructor) => when(isInstanceOf(classConstructor)); | ||
var patterns = /*#__PURE__*/Object.freeze({ | ||
__proto__: null, | ||
optional: optional, | ||
array: array, | ||
intersection: intersection, | ||
union: union, | ||
not: not, | ||
when: when, | ||
select: select, | ||
__: __, | ||
string: string, | ||
number: number, | ||
boolean: boolean, | ||
bigint: bigint, | ||
symbol: symbol, | ||
nullish: nullish, | ||
instanceOf: instanceOf | ||
}); | ||
/** | ||
* #### match | ||
@@ -21,8 +313,2 @@ * | ||
const match = (value) => builder(value, []); | ||
exports.match = match; | ||
/** | ||
* ### builder | ||
* This is the implementation of our pattern matching, using the | ||
* builder pattern. | ||
*/ | ||
const builder = (value, cases) => { | ||
@@ -48,11 +334,10 @@ const run = () => { | ||
const predicates = []; | ||
for (let i = 0; i < args.length - 1; i++) { | ||
const arg = args[i]; | ||
if (typeof arg === 'function') { | ||
predicates.push(arg); | ||
} | ||
else { | ||
patterns.push(arg); | ||
} | ||
// case with guard as second argument | ||
if (args.length === 3 && typeof args[1] === 'function') { | ||
patterns.push(args[0]); | ||
predicates.push(args[1]); | ||
} | ||
else { | ||
patterns.push(...args.slice(0, args.length - 1)); | ||
} | ||
let selected = {}; | ||
@@ -67,4 +352,4 @@ const doesMatch = (value) => Boolean(patterns.some((pattern) => matchPattern(pattern, value, (key, value) => { | ||
select: (value) => Object.keys(selected).length | ||
? symbols.AnonymousSelectKey in selected | ||
? selected[symbols.AnonymousSelectKey] | ||
? anonymousSelectKey in selected | ||
? selected[anonymousSelectKey] | ||
: selected | ||
@@ -93,75 +378,3 @@ : value, | ||
}; | ||
const isObject = (value) => Boolean(value && typeof value === 'object'); | ||
const isGuardPattern = (x) => { | ||
const pattern = x; | ||
return pattern && pattern[symbols.PatternKind] === symbols.Guard; | ||
}; | ||
const isNotPattern = (x) => { | ||
const pattern = x; | ||
return pattern && pattern[symbols.PatternKind] === symbols.Not; | ||
}; | ||
const isSelectPattern = (x) => { | ||
const pattern = x; | ||
return pattern && pattern[symbols.PatternKind] === symbols.Select; | ||
}; | ||
// tells us if the value matches a given pattern. | ||
const matchPattern = (pattern, value, select) => { | ||
if (isObject(pattern)) { | ||
if (isGuardPattern(pattern)) | ||
return Boolean(pattern[symbols.Guard](value)); | ||
if (isSelectPattern(pattern)) { | ||
select(pattern[symbols.Select], value); | ||
return true; | ||
} | ||
if (isNotPattern(pattern)) | ||
return !matchPattern(pattern[symbols.Not], value, select); | ||
if (!isObject(value)) | ||
return false; | ||
if (Array.isArray(pattern)) { | ||
if (!Array.isArray(value)) | ||
return false; | ||
// List pattern | ||
if (pattern.length === 1) { | ||
const selected = {}; | ||
const listSelect = (key, value) => { | ||
selected[key] = (selected[key] || []).concat([value]); | ||
}; | ||
const doesMatch = value.every((v) => matchPattern(pattern[0], v, listSelect)); | ||
if (doesMatch) { | ||
Object.keys(selected).forEach((key) => select(key, selected[key])); | ||
} | ||
return doesMatch; | ||
} | ||
// Tuple pattern | ||
return pattern.length === value.length | ||
? pattern.every((subPattern, i) => matchPattern(subPattern, value[i], select)) | ||
: false; | ||
} | ||
if (pattern instanceof Map) { | ||
if (!(value instanceof Map)) | ||
return false; | ||
return [...pattern.keys()].every((key) => matchPattern(pattern.get(key), value.get(key), select)); | ||
} | ||
if (pattern instanceof Set) { | ||
if (!(value instanceof Set)) | ||
return false; | ||
if (pattern.size === 0) | ||
return value.size === 0; | ||
if (pattern.size === 1) { | ||
const [subPattern] = [...pattern.values()]; | ||
return Object.values(wildcards_1.__).includes(subPattern) | ||
? matchPattern([subPattern], [...value.values()], select) | ||
: value.has(subPattern); | ||
} | ||
return [...pattern.values()].every((subPattern) => value.has(subPattern)); | ||
} | ||
return Object.keys(pattern).every((k) => k in value && | ||
matchPattern( | ||
// @ts-ignore | ||
pattern[k], | ||
// @ts-ignore | ||
value[k], select)); | ||
} | ||
return value === pattern; | ||
}; | ||
function isMatching(...args) { | ||
@@ -176,4 +389,12 @@ if (args.length === 1) { | ||
} | ||
throw new Error(`isMatching wasn't given enough arguments: expected 1 or 2, received ${args.length}.`); | ||
throw new Error(`isMatching wasn't given the right number of arguments: expected 1 or 2, received ${args.length}.`); | ||
} | ||
exports.P = patterns; | ||
exports.__ = __; | ||
exports.instanceOf = instanceOf; | ||
exports.isMatching = isMatching; | ||
exports.match = match; | ||
exports.not = not; | ||
exports.select = select; | ||
exports.when = when; |
@@ -6,3 +6,3 @@ /** | ||
* Symbols have the advantage of not appearing in auto-complete suggestions in | ||
* user defined patterns, and eliminate the admittedly unlikely risk of property | ||
* user defined patterns, and eliminate the risk of property | ||
* overlap between ts-pattern internals and user defined patterns. | ||
@@ -16,15 +16,7 @@ * | ||
*/ | ||
/** @internal This symbol should only be used by ts-pattern's internals. */ | ||
export declare const PatternKind: unique symbol; | ||
export declare type PatternKind = typeof PatternKind; | ||
/** @internal This symbol should only be used by ts-pattern's internals. */ | ||
export declare const Guard: unique symbol; | ||
export declare type Guard = typeof Guard; | ||
/** @internal This symbol should only be used by ts-pattern's internals. */ | ||
export declare const Not: unique symbol; | ||
export declare type Not = typeof Not; | ||
/** @internal This symbol should only be used by ts-pattern's internals. */ | ||
export declare const Select: unique symbol; | ||
export declare type Select = typeof Select; | ||
export declare const AnonymousSelectKey = "@ts-pattern/__anonymous-select-key"; | ||
export declare type AnonymousSelectKey = typeof AnonymousSelectKey; | ||
export declare const toExclude: unique symbol; | ||
export declare type toExclude = typeof toExclude; | ||
export declare const matcher: unique symbol; | ||
export declare type matcher = typeof matcher; | ||
export declare const anonymousSelectKey = "@ts-pattern/anonymous-select-key"; | ||
export declare type anonymousSelectKey = typeof anonymousSelectKey; |
@@ -84,6 +84,3 @@ import { BuildMany } from './BuildMany'; | ||
] ? [...FindUnions<a1, p1, [...path, 0]>, ...FindUnions<a2, p2, [...path, 1]>] : [a, p] extends [readonly [infer a1], readonly [infer p1]] ? FindUnions<a1, p1, [...path, 0]> : [] : a extends Set<any> ? [] : a extends Map<any, any> ? [] : [IsPlainObject<a>, IsPlainObject<p>] extends [true, true] ? Flatten<Values<{ | ||
[k in keyof Required<a> & keyof p]: FindUnions<NonNullable<a[k]>, p[k], [ | ||
...path, | ||
k | ||
]>; | ||
[k in keyof a & keyof p]: FindUnions<a[k], p[k], [...path, k]>; | ||
}>> : []; | ||
@@ -90,0 +87,0 @@ export declare type Distribute<unions extends any[]> = unions extends [ |
@@ -1,4 +0,5 @@ | ||
import type { NotPattern } from './Pattern'; | ||
import type { BuiltInObjects, ExcludeObjectIfContainsNever, IsAny, IsPlainObject, LeastUpperBound } from './helpers'; | ||
export declare type ExtractPreciseValue<a, b> = unknown extends b ? a : IsAny<a> extends true ? b : b extends readonly [] ? [] : b extends NotPattern<infer b1> ? Exclude<a, b1> : b extends readonly (infer bItem)[] ? a extends readonly (infer aItem)[] ? b extends readonly [infer b1, infer b2, infer b3, infer b4, infer b5] ? a extends readonly [infer a1, infer a2, infer a3, infer a4, infer a5] ? ExcludeObjectIfContainsNever<[ | ||
import type { ToExclude } from './Pattern'; | ||
import type { BuiltInObjects, Compute, ExcludeObjectIfContainsNever, IsAny, IsPlainObject, LeastUpperBound } from './helpers'; | ||
import { DeepExclude } from './DeepExclude'; | ||
export declare type ExtractPreciseValue<a, b> = unknown extends b ? a : IsAny<a> extends true ? b : b extends readonly [] ? [] : b extends ToExclude<infer b1> ? DeepExclude<a, b1> : b extends readonly (infer bItem)[] ? a extends readonly (infer aItem)[] ? b extends readonly [infer b1, infer b2, infer b3, infer b4, infer b5] ? a extends readonly [infer a1, infer a2, infer a3, infer a4, infer a5] ? ExcludeObjectIfContainsNever<[ | ||
ExtractPreciseValue<a1, b1>, | ||
@@ -21,4 +22,6 @@ ExtractPreciseValue<a2, b2>, | ||
ExtractPreciseValue<a2, b2> | ||
], '0' | '1'> : LeastUpperBound<a, b> : ExtractPreciseValue<aItem, bItem> extends infer preciseValue ? [preciseValue] extends [never] ? never : preciseValue[] : never : LeastUpperBound<a, b> : b extends Map<infer bk, infer bv> ? a extends Map<infer ak, infer av> ? Map<ExtractPreciseValue<ak, bk>, ExtractPreciseValue<av, bv>> : LeastUpperBound<a, b> : b extends Set<infer bv> ? a extends Set<infer av> ? Set<ExtractPreciseValue<av, bv>> : LeastUpperBound<a, b> : IsPlainObject<b, BuiltInObjects | Error> extends true ? a extends object ? a extends b ? a : b extends a ? b : [keyof a & keyof b] extends [never] ? never : ExcludeObjectIfContainsNever<{ | ||
[k in keyof Required<a>]: k extends keyof b ? ExtractPreciseValue<a[k], b[k]> : a[k]; | ||
}, keyof b & string> : LeastUpperBound<a, b> : LeastUpperBound<a, b>; | ||
], '0' | '1'> : LeastUpperBound<a, b> : b extends readonly [infer b1] ? a extends readonly [infer a1] ? ExcludeObjectIfContainsNever<[ExtractPreciseValue<a1, b1>], '0'> : LeastUpperBound<a, b> : ExtractPreciseValue<aItem, bItem> extends infer preciseValue ? [preciseValue] extends [never] ? never : preciseValue[] : never : LeastUpperBound<a, b> : b extends Map<infer bk, infer bv> ? a extends Map<infer ak, infer av> ? Map<ExtractPreciseValue<ak, bk>, ExtractPreciseValue<av, bv>> : LeastUpperBound<a, b> : b extends Set<infer bv> ? a extends Set<infer av> ? Set<ExtractPreciseValue<av, bv>> : LeastUpperBound<a, b> : IsPlainObject<b, BuiltInObjects | Error> extends true ? a extends object ? a extends b ? a : b extends a ? b : [keyof a & keyof b] extends [never] ? never : ExcludeObjectIfContainsNever<Compute<{ | ||
[k in Exclude<keyof a, keyof b>]: a[k]; | ||
} & { | ||
[k in keyof b]: k extends keyof a ? ExtractPreciseValue<a[k], b[k]> : b[k]; | ||
}>, keyof b & string> : LeastUpperBound<a, b> : LeastUpperBound<a, b>; |
import type * as symbols from '../symbols'; | ||
import type { Cast, IsAny, UnionToIntersection } from './helpers'; | ||
import type { SelectPattern } from './Pattern'; | ||
export declare type FindSelectionUnion<i, p, path extends any[] = []> = IsAny<i> extends true ? never : p extends SelectPattern<infer k> ? { | ||
import type { Cast, Equal, IsAny, UnionToIntersection } from './helpers'; | ||
import type { Matchable, Pattern } from './Pattern'; | ||
declare type SelectionsRecord = Record<string, [unknown, unknown[]]>; | ||
export declare type None = { | ||
type: 'none'; | ||
}; | ||
export declare type Some<key extends string> = { | ||
type: 'some'; | ||
key: key; | ||
}; | ||
export declare type SelectionType = None | Some<string>; | ||
declare type MapOptional<selections> = { | ||
[k in keyof selections]: selections[k] extends [infer v, infer subpath] ? [v | undefined, subpath] : never; | ||
}; | ||
declare type MapList<selections> = { | ||
[k in keyof selections]: selections[k] extends [infer v, infer subpath] ? [v[], subpath] : never; | ||
}; | ||
declare type ReduceFindSelectionUnion<i, ps extends any[], output = never> = ps extends [infer head, ...infer tail] ? ReduceFindSelectionUnion<i, tail, output | FindSelectionUnion<i, head>> : output; | ||
export declare type FindSelectionUnion<i, p, path extends any[] = []> = IsAny<i> extends true ? never : p extends Matchable<any, infer pattern, infer matcherType, infer sel> ? matcherType extends 'array' ? i extends (infer ii)[] ? MapList<FindSelectionUnion<ii, pattern>> : never : matcherType extends 'optional' ? MapOptional<FindSelectionUnion<i, pattern>> : matcherType extends 'or' ? MapOptional<ReduceFindSelectionUnion<i, Cast<pattern, any[]>>> : matcherType extends 'and' ? ReduceFindSelectionUnion<i, Cast<pattern, any[]>> : sel extends None ? never : sel extends Some<infer k> ? { | ||
[kk in k]: [i, path]; | ||
} : p extends readonly (infer pp)[] ? i extends readonly (infer ii)[] ? [i, p] extends [ | ||
} : never : p extends readonly (infer pp)[] ? i extends readonly (infer ii)[] ? [i, p] extends [ | ||
readonly [infer i1, infer i2, infer i3, infer i4, infer i5], | ||
@@ -18,11 +34,3 @@ readonly [infer p1, infer p2, infer p3, infer p4, infer p5] | ||
readonly [infer p1, infer p2] | ||
] ? FindSelectionUnion<i1, p1, [...path, 1]> | FindSelectionUnion<i2, p2, [...path, 2]> : FindSelectionUnion<ii, pp, [ | ||
...path, | ||
number | ||
]> extends infer selectionUnion ? { | ||
[k in keyof selectionUnion]: selectionUnion[k] extends [ | ||
infer v, | ||
infer path | ||
] ? [v[], path] : never; | ||
} : never : never : p extends object ? i extends object ? { | ||
] ? FindSelectionUnion<i1, p1, [...path, 1]> | FindSelectionUnion<i2, p2, [...path, 2]> : FindSelectionUnion<ii, pp, [...path, 1]> : never : p extends object ? i extends object ? { | ||
[k in keyof p]: k extends keyof i ? FindSelectionUnion<i[k], p[k], [...path, k]> : never; | ||
@@ -36,8 +44,11 @@ }[keyof p] : never : never; | ||
} & a; | ||
declare type SelectionToArgs<selections extends Record<string, [unknown, unknown]>, i> = [keyof selections] extends [never] ? i : symbols.AnonymousSelectKey extends keyof selections ? [ | ||
selections[symbols.AnonymousSelectKey][1] | ||
] extends [never] ? SeveralAnonymousSelectError : keyof selections extends symbols.AnonymousSelectKey ? selections[symbols.AnonymousSelectKey][0] : MixedNamedAndAnonymousSelectError : { | ||
export declare type SelectionToArgs<selections extends SelectionsRecord, i> = [ | ||
keyof selections | ||
] extends [never] ? i : symbols.anonymousSelectKey extends keyof selections ? [ | ||
selections[symbols.anonymousSelectKey][1] | ||
] extends [never] ? SeveralAnonymousSelectError : keyof selections extends symbols.anonymousSelectKey ? selections[symbols.anonymousSelectKey][0] : MixedNamedAndAnonymousSelectError : { | ||
[k in keyof selections]: selections[k][0]; | ||
}; | ||
export declare type FindSelected<i, p> = SelectionToArgs<Cast<UnionToIntersection<{} | FindSelectionUnion<i, p>>, Record<string, [unknown, unknown]>>, i>; | ||
export declare type Selections<i, p> = Cast<UnionToIntersection<{} | FindSelectionUnion<i, p>>, SelectionsRecord>; | ||
export declare type FindSelected<i, p> = Equal<p, Pattern<i>> extends true ? i : SelectionToArgs<Selections<i, p>, i>; | ||
export {}; |
@@ -36,3 +36,3 @@ export declare type ValueOf<a> = a extends any[] ? a[number] : a[keyof a]; | ||
readonly [Symbol.toStringTag]: string; | ||
}; | ||
} | any[]; | ||
export declare type IsPlainObject<o, excludeUnion = BuiltInObjects> = o extends object ? o extends string | excludeUnion ? false : true : false; | ||
@@ -48,1 +48,6 @@ export declare type Compute<a extends any> = a extends BuiltInObjects ? a : { | ||
export declare type Union<a, b> = [b] extends [a] ? a : [a] extends [b] ? b : a | b; | ||
/** | ||
* GuardValue returns the value guarded by a type guard function. | ||
*/ | ||
export declare type GuardValue<F> = F extends (value: any) => value is infer b ? b : F extends (value: infer a) => unknown ? a : never; | ||
export declare type GuardFunction<input, narrowed> = ((value: input) => value is Cast<narrowed, input>) | ((value: input) => boolean); |
@@ -1,3 +0,12 @@ | ||
import { IsPlainObject, Primitives, IsLiteral } from './helpers'; | ||
import type { SelectPattern, GuardPattern, NotPattern } from './Pattern'; | ||
import { DeepExclude } from './DeepExclude'; | ||
import { IsPlainObject, Primitives, IsLiteral, ValueOf, Compute, Cast } from './helpers'; | ||
import type { Matchable, ToExclude } from './Pattern'; | ||
declare type OptionalKeys<p> = ValueOf<{ | ||
[k in keyof p]: p[k] extends Matchable<any, any, infer matcherType> ? matcherType extends 'optional' ? k : never : never; | ||
}>; | ||
declare type ReduceUnion<tuple extends any[], output = never> = tuple extends readonly [ | ||
infer p, | ||
...infer tail | ||
] ? ReduceUnion<tail, output | InvertPattern<p>> : output; | ||
declare type ReduceIntersection<tuple extends any[], output = unknown> = tuple extends readonly [infer p, ...infer tail] ? ReduceIntersection<tail, output & InvertPattern<p>> : output; | ||
/** | ||
@@ -8,3 +17,3 @@ * ### InvertPattern | ||
*/ | ||
export declare type InvertPattern<p> = p extends SelectPattern<any> ? unknown : p extends GuardPattern<infer p1, infer p2> ? [p2] extends [never] ? p1 : p2 : p extends NotPattern<infer a1> ? NotPattern<InvertPattern<a1>> : p extends Primitives ? p : p extends readonly (infer pp)[] ? p extends readonly [infer p1, infer p2, infer p3, infer p4, infer p5] ? [ | ||
export declare type InvertPattern<p> = p extends Matchable<infer input, infer narrowed, infer matcherType, any> ? matcherType extends 'not' ? ToExclude<InvertPattern<narrowed>> : matcherType extends 'array' ? InvertPattern<narrowed>[] : matcherType extends 'optional' ? InvertPattern<narrowed> | undefined : matcherType extends 'and' ? ReduceIntersection<Cast<narrowed, any[]>> : matcherType extends 'or' ? ReduceUnion<Cast<narrowed, any[]>> : [narrowed] extends [never] ? input : narrowed : p extends Primitives ? p : p extends readonly (infer pp)[] ? p extends readonly [infer p1, infer p2, infer p3, infer p4, infer p5] ? [ | ||
InvertPattern<p1>, | ||
@@ -20,25 +29,35 @@ InvertPattern<p2>, | ||
InvertPattern<p4> | ||
] : p extends readonly [infer p1, infer p2, infer p3] ? [InvertPattern<p1>, InvertPattern<p2>, InvertPattern<p3>] : p extends readonly [infer p1, infer p2] ? [InvertPattern<p1>, InvertPattern<p2>] : InvertPattern<pp>[] : p extends Map<infer pk, infer pv> ? Map<pk, InvertPattern<pv>> : p extends Set<infer pv> ? Set<InvertPattern<pv>> : IsPlainObject<p> extends true ? { | ||
[k in keyof p]: InvertPattern<p[k]>; | ||
} : p; | ||
] : p extends readonly [infer p1, infer p2, infer p3] ? [InvertPattern<p1>, InvertPattern<p2>, InvertPattern<p3>] : p extends readonly [infer p1, infer p2] ? [InvertPattern<p1>, InvertPattern<p2>] : p extends readonly [infer p1] ? [InvertPattern<p1>] : p extends readonly [] ? [] : InvertPattern<pp>[] : p extends Map<infer pk, infer pv> ? Map<pk, InvertPattern<pv>> : p extends Set<infer pv> ? Set<InvertPattern<pv>> : IsPlainObject<p> extends true ? Compute<{ | ||
[k in Exclude<keyof p, OptionalKeys<p>>]: InvertPattern<p[k]>; | ||
} & { | ||
[k in OptionalKeys<p>]?: InvertPattern<p[k]>; | ||
}> : p; | ||
export declare type ReduceIntersectionForExclude<tuple extends any[], i, output = unknown> = tuple extends readonly [infer p, ...infer tail] ? ReduceIntersectionForExclude<tail, i, output & InvertPatternForExclude<p, i, unknown>> : output; | ||
export declare type ReduceUnionForExclude<tuple extends any[], i, output = never> = tuple extends readonly [infer p, ...infer tail] ? ReduceUnionForExclude<tail, i, output | InvertPatternForExclude<p, i, never>> : output; | ||
/** | ||
* ### InvertPatternForExclude | ||
*/ | ||
export declare type InvertPatternForExclude<p, i> = p extends NotPattern<infer p1> ? Exclude<i, p1> : p extends SelectPattern<any> ? unknown : p extends GuardPattern<any, infer p1> ? p1 : p extends Primitives ? IsLiteral<p> extends true ? p : IsLiteral<i> extends true ? p : never : p extends readonly (infer pp)[] ? i extends readonly (infer ii)[] ? p extends readonly [infer p1, infer p2, infer p3, infer p4, infer p5] ? i extends readonly [infer i1, infer i2, infer i3, infer i4, infer i5] ? [ | ||
InvertPatternForExclude<p1, i1>, | ||
InvertPatternForExclude<p2, i2>, | ||
InvertPatternForExclude<p3, i3>, | ||
InvertPatternForExclude<p4, i4>, | ||
InvertPatternForExclude<p5, i5> | ||
] : never : p extends readonly [infer p1, infer p2, infer p3, infer p4] ? i extends readonly [infer i1, infer i2, infer i3, infer i4] ? [ | ||
InvertPatternForExclude<p1, i1>, | ||
InvertPatternForExclude<p2, i2>, | ||
InvertPatternForExclude<p3, i3>, | ||
InvertPatternForExclude<p4, i4> | ||
] : never : p extends readonly [infer p1, infer p2, infer p3] ? i extends readonly [infer i1, infer i2, infer i3] ? [ | ||
InvertPatternForExclude<p1, i1>, | ||
InvertPatternForExclude<p2, i2>, | ||
InvertPatternForExclude<p3, i3> | ||
] : never : p extends readonly [infer p1, infer p2] ? i extends readonly [infer i1, infer i2] ? [InvertPatternForExclude<p1, i1>, InvertPatternForExclude<p2, i2>] : never : InvertPatternForExclude<pp, ii>[] : never : p extends Map<infer pk, infer pv> ? i extends Map<any, infer iv> ? Map<pk, InvertPatternForExclude<pv, iv>> : never : p extends Set<infer pv> ? i extends Set<infer iv> ? Set<InvertPatternForExclude<pv, iv>> : never : IsPlainObject<p> extends true ? i extends object ? [keyof p & keyof i] extends [never] ? never : { | ||
[k in keyof p]: k extends keyof i ? InvertPatternForExclude<p[k], i[k]> : p[k]; | ||
} : never : never; | ||
export declare type InvertPatternForExclude<p, i, empty = never> = p extends Matchable<any, infer narrowed, infer matcherType, any, infer excluded> ? matcherType extends 'not' ? InvertPatternForExclude<narrowed, i, unknown> extends infer inv ? [inv] extends [never] ? empty : DeepExclude<i, inv> : empty : matcherType extends 'array' ? i extends readonly (infer ii)[] ? InvertPatternForExclude<narrowed, ii, empty>[] : empty : matcherType extends 'optional' ? InvertPatternForExclude<narrowed, i, empty> | undefined : matcherType extends 'and' ? ReduceIntersectionForExclude<Cast<narrowed, any[]>, i> : matcherType extends 'or' ? ReduceUnionForExclude<Cast<narrowed, any[]>, i> : excluded : p extends Primitives ? IsLiteral<p> extends true ? p : IsLiteral<i> extends true ? p : empty : p extends readonly (infer pp)[] ? i extends readonly (infer ii)[] ? p extends readonly [infer p1, infer p2, infer p3, infer p4, infer p5] ? i extends readonly [infer i1, infer i2, infer i3, infer i4, infer i5] ? readonly [ | ||
InvertPatternForExclude<p1, i1, empty>, | ||
InvertPatternForExclude<p2, i2, empty>, | ||
InvertPatternForExclude<p3, i3, empty>, | ||
InvertPatternForExclude<p4, i4, empty>, | ||
InvertPatternForExclude<p5, i5, empty> | ||
] : empty : p extends readonly [infer p1, infer p2, infer p3, infer p4] ? i extends readonly [infer i1, infer i2, infer i3, infer i4] ? readonly [ | ||
InvertPatternForExclude<p1, i1, empty>, | ||
InvertPatternForExclude<p2, i2, empty>, | ||
InvertPatternForExclude<p3, i3, empty>, | ||
InvertPatternForExclude<p4, i4, empty> | ||
] : empty : p extends readonly [infer p1, infer p2, infer p3] ? i extends readonly [infer i1, infer i2, infer i3] ? readonly [ | ||
InvertPatternForExclude<p1, i1, empty>, | ||
InvertPatternForExclude<p2, i2, empty>, | ||
InvertPatternForExclude<p3, i3, empty> | ||
] : empty : p extends readonly [infer p1, infer p2] ? i extends readonly [infer i1, infer i2] ? readonly [ | ||
InvertPatternForExclude<p1, i1, empty>, | ||
InvertPatternForExclude<p2, i2, empty> | ||
] : empty : p extends readonly [infer p1] ? i extends readonly [infer i1] ? readonly [InvertPatternForExclude<p1, i1, empty>] : empty : p extends readonly [] ? [] : InvertPatternForExclude<pp, ii, empty>[] : empty : p extends Map<infer pk, infer pv> ? i extends Map<any, infer iv> ? Map<pk, InvertPatternForExclude<pv, iv, empty>> : empty : p extends Set<infer pv> ? i extends Set<infer iv> ? Set<InvertPatternForExclude<pv, iv, empty>> : empty : IsPlainObject<p> extends true ? i extends object ? [keyof p & keyof i] extends [never] ? empty : Compute<{ | ||
[k in Exclude<keyof p, OptionalKeys<p>>]: k extends keyof i ? InvertPatternForExclude<p[k], i[k], empty> : InvertPattern<p[k]>; | ||
} & { | ||
[k in OptionalKeys<p>]?: k extends keyof i ? InvertPatternForExclude<p[k], i[k], empty> : InvertPattern<p[k]>; | ||
}> : empty : empty; | ||
export {}; |
@@ -1,3 +0,3 @@ | ||
import { Primitives, IsPlainObject } from './helpers'; | ||
export declare type IsMatching<a, p> = unknown extends p ? true : p extends Primitives ? p extends a ? true : false : [p, a] extends [readonly any[], readonly any[]] ? [p, a] extends [ | ||
import { Primitives, IsPlainObject, IsUnion } from './helpers'; | ||
export declare type IsMatching<a, p> = true extends IsUnion<a> | IsUnion<p> ? true extends (p extends any ? (a extends any ? IsMatching<a, p> : never) : never) ? true : false : unknown extends p ? true : p extends Primitives ? p extends a ? true : false : [p, a] extends [readonly any[], readonly any[]] ? [p, a] extends [ | ||
readonly [infer p1, infer p2, infer p3, infer p4, infer p5], | ||
@@ -4,0 +4,0 @@ readonly [infer a1, infer a2, infer a3, infer a4, infer a5] |
@@ -1,6 +0,6 @@ | ||
import type { Pattern, GuardValue, GuardPattern } from './Pattern'; | ||
import type { Pattern, Matchable } from './Pattern'; | ||
import type { ExtractPreciseValue } from './ExtractPreciseValue'; | ||
import type { InvertPatternForExclude, InvertPattern } from './InvertPattern'; | ||
import type { DeepExclude } from './DeepExclude'; | ||
import type { WithDefault, Union } from './helpers'; | ||
import type { WithDefault, Union, GuardValue } from './helpers'; | ||
import type { FindSelected } from './FindSelected'; | ||
@@ -17,3 +17,3 @@ export declare type MatchedValue<a, invpattern> = WithDefault<ExtractPreciseValue<a, invpattern>, a>; | ||
*/ | ||
export declare type Match<i, o, patternValueTuples extends [any, any] = never, inferredOutput = never> = { | ||
export declare type Match<i, o, patternValueTuples extends [any, any][] = [], inferredOutput = never> = { | ||
/** | ||
@@ -25,6 +25,8 @@ * #### Match.with | ||
**/ | ||
with<p extends Pattern<i>, c, value = MatchedValue<i, InvertPattern<p>>>(pattern: p, handler: (selections: FindSelected<value, p>, value: value) => PickReturnValue<o, c>): Match<i, o, patternValueTuples | [p, value], Union<inferredOutput, c>>; | ||
with<p1 extends Pattern<i>, p2 extends Pattern<i>, c, p = p1 | p2, value = p extends any ? MatchedValue<i, InvertPattern<p>> : never>(pattern1: p1, pattern2: p2, handler: (value: value) => PickReturnValue<o, c>): Match<i, o, patternValueTuples | (p extends any ? [p, value] : never), Union<inferredOutput, c>>; | ||
with<pat extends Pattern<i>, pred extends (value: MatchedValue<i, InvertPattern<pat>>) => unknown, c, value = GuardValue<pred>>(pattern: pat, predicate: pred, handler: (selections: FindSelected<value, pat>, value: value) => PickReturnValue<o, c>): Match<i, o, patternValueTuples | (pred extends (value: any) => value is infer narrowed ? [GuardPattern<unknown, narrowed>, value] : never), Union<inferredOutput, c>>; | ||
with<ps extends [Pattern<i>, ...Pattern<i>[]], c, p = ps[number], value = p extends any ? MatchedValue<i, InvertPattern<p>> : never>(...args: [...patterns: ps, handler: (value: value) => PickReturnValue<o, c>]): Match<i, o, patternValueTuples | (p extends any ? [p, value] : never), Union<inferredOutput, c>>; | ||
with<p extends Pattern<i>, c, value = MatchedValue<i, InvertPattern<p>>>(pattern: p, handler: (selections: FindSelected<value, p>, value: value) => PickReturnValue<o, c>): Match<i, o, [...patternValueTuples, [p, value]], Union<inferredOutput, c>>; | ||
with<pat extends Pattern<i>, pred extends (value: MatchedValue<i, InvertPattern<pat>>) => unknown, c, value = GuardValue<pred>>(pattern: pat, predicate: pred, handler: (selections: FindSelected<value, pat>, value: value) => PickReturnValue<o, c>): Match<i, o, pred extends (value: any) => value is infer narrowed ? [...patternValueTuples, [Matchable<unknown, narrowed>, value]] : patternValueTuples, Union<inferredOutput, c>>; | ||
with<ps extends [Pattern<i>, ...Pattern<i>[]], c, p = ps[number], value = p extends any ? MatchedValue<i, InvertPattern<p>> : never>(...args: [...patterns: ps, handler: (value: value) => PickReturnValue<o, c>]): Match<i, o, [ | ||
...patternValueTuples, | ||
...MakeTuples<ps, value> | ||
], Union<inferredOutput, c>>; | ||
/** | ||
@@ -36,3 +38,3 @@ * #### Match.when | ||
**/ | ||
when: <pred extends (value: i) => unknown, c, value = GuardValue<pred>>(predicate: pred, handler: (value: value) => PickReturnValue<o, c>) => Match<i, o, patternValueTuples | (pred extends (value: any) => value is infer narrowed ? [GuardPattern<unknown, narrowed>, value] : never), Union<inferredOutput, c>>; | ||
when: <pred extends (value: i) => unknown, c, value = GuardValue<pred>>(predicate: pred, handler: (value: value) => PickReturnValue<o, c>) => Match<i, o, pred extends (value: any) => value is infer narrowed ? [...patternValueTuples, [Matchable<unknown, narrowed>, value]] : patternValueTuples, Union<inferredOutput, c>>; | ||
/** | ||
@@ -64,3 +66,10 @@ * #### Match.otherwise | ||
}; | ||
declare type DeepExcludeAll<a, tuple extends [any, any]> = DeepExclude<a, tuple extends any ? InvertPatternForExclude<tuple[0], tuple[1]> : never>; | ||
declare type DeepExcludeAll<a, tupleList extends any[]> = tupleList extends [ | ||
[ | ||
infer p, | ||
infer v | ||
], | ||
...infer tail | ||
] ? DeepExcludeAll<DeepExclude<a, InvertPatternForExclude<p, v>>, tail> : a; | ||
declare type MakeTuples<ps extends any[], value, output extends any[] = []> = ps extends [infer p, ...infer tail] ? MakeTuples<tail, value, [...output, [p, value]]> : output; | ||
export {}; |
import type * as symbols from '../symbols'; | ||
import { Primitives, IsPlainObject } from './helpers'; | ||
/** | ||
* GuardValue returns the value guarded by a type guard function. | ||
*/ | ||
export declare type GuardValue<F> = F extends (value: any) => value is infer b ? b : F extends (value: infer a) => unknown ? a : never; | ||
export declare type GuardFunction<a, b extends a> = ((value: a) => value is b) | ((value: a) => boolean); | ||
export declare type GuardPattern<a, b extends a = never> = { | ||
/** @internal This property should only be used by ts-pattern's internals. */ | ||
[symbols.PatternKind]: symbols.Guard; | ||
/** @internal This property should only be used by ts-pattern's internals. */ | ||
[symbols.Guard]: GuardFunction<a, b>; | ||
import { Primitives, Compute, Cast, IsPlainObject, IsUnion, ValueOf } from './helpers'; | ||
import { None, Some, SelectionType } from './FindSelected'; | ||
export declare type MatcherType = 'not' | 'optional' | 'or' | 'and' | 'array' | 'default'; | ||
export declare type MatcherProtocol<input, narrowed, matcherType extends MatcherType = 'default', selections extends SelectionType = None, excluded = narrowed> = { | ||
match: (value: input) => MatchResult; | ||
getSelectionKeys?: () => string[]; | ||
matcherType?: matcherType; | ||
}; | ||
export declare type NotPattern<a> = { | ||
/** @internal This property should only be used by ts-pattern's internals. */ | ||
[symbols.PatternKind]: symbols.Not; | ||
/** @internal This property should only be used by ts-pattern's internals. */ | ||
[symbols.Not]: Pattern<a>; | ||
export declare type MatchResult = { | ||
matched: boolean; | ||
selections?: Record<string, any>; | ||
}; | ||
export declare type AnonymousSelectPattern = SelectPattern<symbols.AnonymousSelectKey>; | ||
export declare type SelectPattern<k extends string> = { | ||
/** @internal This property should only be used by ts-pattern's internals. */ | ||
[symbols.PatternKind]: symbols.Select; | ||
/** @internal This property should only be used by ts-pattern's internals. */ | ||
[symbols.Select]: k; | ||
export interface Matchable<input, narrowed, matcherType extends MatcherType = 'default', selections extends SelectionType = None, excluded = narrowed> { | ||
[symbols.matcher](): MatcherProtocol<input, narrowed, matcherType, selections, excluded>; | ||
} | ||
declare type AnyMatchable = Matchable<unknown, unknown, any, any>; | ||
export declare type OptionalP<input, p> = Matchable<input, p, 'optional'>; | ||
export declare type ArrayP<input, p> = Matchable<input, p, 'array'>; | ||
export declare type AndP<input, ps> = Matchable<input, ps, 'and'>; | ||
export declare type OrP<input, ps> = Matchable<input, ps, 'or'>; | ||
export declare type NotP<input, p> = Matchable<input, p, 'not'>; | ||
export declare type GuardP<input, narrowed> = Matchable<input, narrowed>; | ||
export declare type SelectP<key extends string> = Matchable<unknown, never, 'default', Some<key>, unknown>; | ||
export interface ToExclude<a> { | ||
[symbols.toExclude]: a; | ||
} | ||
export declare type UnknownPattern = readonly [Pattern<unknown>, ...Pattern<unknown>[]] | { | ||
readonly [k: string]: Pattern<unknown>; | ||
} | Set<Pattern<unknown>> | Map<unknown, Pattern<unknown>> | Primitives | AnyMatchable; | ||
declare type Keys<a> = keyof Compute<a> extends infer shared ? { | ||
shared: shared; | ||
others: ValueOf<{ | ||
[k in keyof a]: k extends shared ? never : k; | ||
}>; | ||
} : never; | ||
declare type HasObjects<a> = true extends (a extends object ? IsPlainObject<a> : false) ? true : false; | ||
declare type FilterObjects<a> = a extends object ? IsPlainObject<a> extends true ? a : never : never; | ||
declare type ExcludeObjects<a> = a extends object ? IsPlainObject<a> extends true ? never : a : a; | ||
declare type PartitionObjects<a> = { | ||
objects: FilterObjects<a>; | ||
others: ExcludeObjects<a>; | ||
}; | ||
/** | ||
* ### Pattern | ||
* Patterns can be any (nested) javascript value. | ||
* They can also be a "wildcards", like `__`. | ||
*/ | ||
export declare type Pattern<a> = SelectPattern<string> | GuardPattern<a, a> | NotPattern<a | any> | (a extends Primitives ? a : a extends readonly (infer i)[] ? a extends readonly [infer a1, infer a2, infer a3, infer a4, infer a5] ? readonly [ | ||
declare type StructuralPattern<a> = [ | ||
IsUnion<a>, | ||
HasObjects<a> | ||
] extends [true, true] ? PartitionObjects<a> extends { | ||
objects: infer objects; | ||
others: infer othersValues; | ||
} ? (Keys<objects> extends { | ||
shared: infer sharedKeys; | ||
others: infer otherKeys; | ||
} ? Compute<{ | ||
readonly [k in sharedKeys & keyof objects]?: Pattern<objects[k]>; | ||
} & { | ||
readonly [k in Cast<otherKeys, string>]?: objects extends any ? k extends keyof objects ? Pattern<objects[k]> : never : never; | ||
}> : never) | ([othersValues] extends [never] ? never : othersValues extends any ? StructuralPattern<othersValues> : never) : never : a extends Primitives ? a : unknown extends a ? UnknownPattern : a extends readonly (infer i)[] ? a extends readonly [infer a1, infer a2, infer a3, infer a4, infer a5] ? readonly [ | ||
Pattern<a1>, | ||
@@ -38,3 +63,3 @@ Pattern<a2>, | ||
Pattern<a5> | ||
] : a extends readonly [infer a1, infer a2, infer a3, infer a4] ? readonly [Pattern<a1>, Pattern<a2>, Pattern<a3>, Pattern<a4>] : a extends readonly [infer a1, infer a2, infer a3] ? readonly [Pattern<a1>, Pattern<a2>, Pattern<a3>] : a extends readonly [infer a1, infer a2] ? readonly [Pattern<a1>, Pattern<a2>] : readonly [] | readonly [Pattern<i>] | readonly [Pattern<i>, Pattern<i>] | readonly [Pattern<i>, Pattern<i>, Pattern<i>] | readonly [Pattern<i>, Pattern<i>, Pattern<i>, Pattern<i>] | readonly [ | ||
] : a extends readonly [infer a1, infer a2, infer a3, infer a4] ? readonly [Pattern<a1>, Pattern<a2>, Pattern<a3>, Pattern<a4>] : a extends readonly [infer a1, infer a2, infer a3] ? readonly [Pattern<a1>, Pattern<a2>, Pattern<a3>] : a extends readonly [infer a1, infer a2] ? readonly [Pattern<a1>, Pattern<a2>] : a extends readonly [infer a1] ? readonly [Pattern<a1>] : readonly [] | readonly [Pattern<i>] | readonly [Pattern<i>, Pattern<i>] | readonly [Pattern<i>, Pattern<i>, Pattern<i>] | readonly [Pattern<i>, Pattern<i>, Pattern<i>, Pattern<i>] | readonly [ | ||
Pattern<i>, | ||
@@ -45,4 +70,11 @@ Pattern<i>, | ||
Pattern<i> | ||
] : a extends Map<infer k, infer v> ? Map<k, Pattern<v>> : a extends Set<infer v> ? Set<Pattern<v>> : IsPlainObject<a> extends true ? { | ||
] : a extends Map<infer k, infer v> ? Map<k, Pattern<v>> : a extends Set<infer v> ? Set<Pattern<v>> : a extends object ? { | ||
readonly [k in keyof a]?: Pattern<a[k]>; | ||
} : a); | ||
} : a; | ||
/** | ||
* ### Pattern | ||
* Patterns can be any (nested) javascript value. | ||
* They can also be a "wildcards", like `__`. | ||
*/ | ||
export declare type Pattern<a> = Matchable<a, unknown, any, any> | StructuralPattern<a>; | ||
export {}; |
{ | ||
"name": "ts-pattern", | ||
"version": "3.3.4", | ||
"version": "4.0.0-rc.0", | ||
"description": " The exhaustive Pattern Matching library for TypeScript.", | ||
"main": "lib/index.js", | ||
"module": "lib/index.esm.js", | ||
"types": "lib/index.d.ts", | ||
"scripts": { | ||
"build": "rimraf lib && tsc", | ||
"build": "rimraf lib && rollup -c", | ||
"prepublishOnly": "npm run test && npm run build", | ||
"test": "jest", | ||
"perf": "tsc --project tests/tsconfig.json --noEmit --extendedDiagnostics" | ||
"perf": "tsc --project tests/tsconfig.json --noEmit --extendedDiagnostics", | ||
"fmt": "prettier --write ." | ||
}, | ||
@@ -37,9 +39,18 @@ "files": [ | ||
"devDependencies": { | ||
"@babel/core": "^7.16.7", | ||
"@babel/preset-env": "^7.16.7", | ||
"@rollup/plugin-babel": "^5.3.0", | ||
"@rollup/plugin-commonjs": "^21.0.1", | ||
"@rollup/plugin-node-resolve": "^13.1.2", | ||
"@rollup/plugin-typescript": "^8.3.0", | ||
"@types/jest": "^27.0.2", | ||
"jest": "^27.4.5", | ||
"prettier": "^2.2.1", | ||
"prettier": "^2.5.1", | ||
"rimraf": "^3.0.2", | ||
"rollup": "^2.62.0", | ||
"rollup-plugin-terser": "^7.0.2", | ||
"ts-jest": "^27.1.2", | ||
"tslib": "^2.3.1", | ||
"typescript": "^4.5.4" | ||
} | ||
} |
@@ -108,3 +108,2 @@ <h1 align="center">ts-pattern</h1> | ||
- [`__.nullish` wildcard](#__nullish-wildcard) | ||
- [`__.NaN` wildcard](#__nan-wildcard) | ||
- [Objects](#objects) | ||
@@ -761,22 +760,2 @@ - [Lists (arrays)](#lists-arrays) | ||
#### `__.NaN` wildcard | ||
The `__.NaN` pattern will match `NaN` values. | ||
Note that `__.number` also matches `NaNs`, but this pattern lets you | ||
explicitly match them if you want to handle them separately: | ||
```ts | ||
import { match, __ } from 'ts-pattern'; | ||
const input = NaN; | ||
const output = match<number>(input) | ||
.with(__.NaN, () => 'This is not a number!') | ||
.with(__.number, () => 'This is a number!') | ||
.exhaustive(); | ||
console.log(output); | ||
// => 'This is not a number!' | ||
``` | ||
#### Objects | ||
@@ -783,0 +762,0 @@ |
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
Major refactor
Supply chain riskPackage has recently undergone a major refactor. It may be unstable or indicate significant internal changes. Use caution when updating to versions that include significant changes.
Found 1 instance in 1 package
No v1
QualityPackage is not semver >=1. This means it is not stable and does not support ^ ranges.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
102090
1444
15
22
1
1087
1