@cjser/ts-pattern 5.9.0-cjser.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +1776 -0
- package/dist/errors.d.cts +8 -0
- package/dist/errors.d.ts +8 -0
- package/dist/index.cjs +2 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.cts +5 -0
- package/dist/index.d.ts +5 -0
- package/dist/index.js +2 -0
- package/dist/index.js.map +1 -0
- package/dist/index.umd.js +2 -0
- package/dist/index.umd.js.map +1 -0
- package/dist/internals/helpers.d.cts +12 -0
- package/dist/internals/helpers.d.ts +12 -0
- package/dist/internals/symbols.d.cts +24 -0
- package/dist/internals/symbols.d.ts +24 -0
- package/dist/is-matching.d.cts +40 -0
- package/dist/is-matching.d.ts +40 -0
- package/dist/match.d.cts +19 -0
- package/dist/match.d.ts +19 -0
- package/dist/patterns.d.cts +345 -0
- package/dist/patterns.d.ts +345 -0
- package/dist/types/BuildMany.d.cts +22 -0
- package/dist/types/BuildMany.d.ts +22 -0
- package/dist/types/DeepExclude.d.cts +2 -0
- package/dist/types/DeepExclude.d.ts +2 -0
- package/dist/types/DistributeUnions.d.cts +111 -0
- package/dist/types/DistributeUnions.d.ts +111 -0
- package/dist/types/ExtractPreciseValue.d.cts +27 -0
- package/dist/types/ExtractPreciseValue.d.ts +27 -0
- package/dist/types/FindSelected.d.cts +78 -0
- package/dist/types/FindSelected.d.ts +78 -0
- package/dist/types/InvertPattern.d.cts +104 -0
- package/dist/types/InvertPattern.d.ts +104 -0
- package/dist/types/IsMatching.d.cts +13 -0
- package/dist/types/IsMatching.d.ts +13 -0
- package/dist/types/Match.d.cts +171 -0
- package/dist/types/Match.d.ts +171 -0
- package/dist/types/Pattern.d.cts +401 -0
- package/dist/types/Pattern.d.ts +401 -0
- package/dist/types/helpers.d.cts +80 -0
- package/dist/types/helpers.d.ts +80 -0
- package/dist/types/index.d.cts +1 -0
- package/dist/types/index.d.ts +1 -0
- package/dist-cjser/index.cjs +319 -0
- package/package.json +135 -0
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
import { DeepExclude } from './DeepExclude.js';
|
|
2
|
+
import { IsPlainObject, Primitives, IsLiteral, ValueOf, Compute, Equal, Extends, Not, All, NonLiteralPrimitive, MaybeAddReadonly, IsReadonlyArray, MapKey, MapValue, SetValue, ExtractPlainObject, GetKey, Call, Fn, ReadonlyArrayValue, WithDefault, RecordKey, RecordValue } from './helpers.js';
|
|
3
|
+
import type { Matcher, Pattern, Override, AnyMatcher } from './Pattern.js';
|
|
4
|
+
type OptionalKeys<p> = ValueOf<{
|
|
5
|
+
[k in keyof p]: 0 extends 1 & p[k] ? never : p[k] extends Matcher<any, any, infer matcherType> ? matcherType extends 'optional' ? k : never : never;
|
|
6
|
+
}>;
|
|
7
|
+
type ReduceUnion<tuple extends readonly any[], i, output = never> = tuple extends readonly [infer p, ...infer tail] ? ReduceUnion<tail, i, output | InvertPatternInternal<p, i>> : output;
|
|
8
|
+
type ReduceIntersection<tuple extends readonly any[], i, output = unknown> = tuple extends readonly [infer p, ...infer tail] ? ReduceIntersection<tail, i, output & InvertPatternInternal<p, i>> : output;
|
|
9
|
+
type InvertArrayPattern<p, i, startOutput extends any[] = [], endOutput extends any[] = []> = i extends readonly (infer ii)[] ? p extends readonly [] ? [...startOutput, ...endOutput] : p extends readonly [infer p1, ...infer pRest] ? i extends readonly [infer i1, ...infer iRest] ? InvertArrayPattern<pRest, iRest, [
|
|
10
|
+
...startOutput,
|
|
11
|
+
InvertPatternInternal<p1, i1>
|
|
12
|
+
], endOutput> : InvertArrayPattern<pRest, ii[], [
|
|
13
|
+
...startOutput,
|
|
14
|
+
InvertPatternInternal<p1, ii>
|
|
15
|
+
], endOutput> : p extends readonly [...infer pInit, infer p1] ? i extends readonly [...infer iInit, infer i1] ? InvertArrayPattern<pInit, iInit, startOutput, [
|
|
16
|
+
...endOutput,
|
|
17
|
+
InvertPatternInternal<p1, i1>
|
|
18
|
+
]> : InvertArrayPattern<pInit, ii[], startOutput, [
|
|
19
|
+
...endOutput,
|
|
20
|
+
InvertPatternInternal<p1, ii>
|
|
21
|
+
]> : p extends readonly [...(readonly (infer pRest & AnyMatcher)[])] ? [
|
|
22
|
+
...startOutput,
|
|
23
|
+
...Extract<InvertPatternInternal<pRest, i>, readonly any[]>,
|
|
24
|
+
...endOutput
|
|
25
|
+
] : [...startOutput, ...InvertPatternInternal<ValueOf<p>, ii>[], ...endOutput] : never;
|
|
26
|
+
/**
|
|
27
|
+
* ### InvertPatternInternal
|
|
28
|
+
* Since patterns have special wildcard values, we need a way
|
|
29
|
+
* to transform a pattern into the type of value it represents
|
|
30
|
+
*/
|
|
31
|
+
export type InvertPattern<p, input> = Equal<Pattern<input>, p> extends true ? never : InvertPatternInternal<p, input>;
|
|
32
|
+
type InvertPatternInternal<p, input> = 0 extends 1 & p ? never : p extends Matcher<infer _input, infer subpattern, infer matcherType, any, infer narrowedOrFn> ? {
|
|
33
|
+
not: DeepExclude<input, InvertPatternInternal<subpattern, input>>;
|
|
34
|
+
select: InvertPatternInternal<subpattern, input>;
|
|
35
|
+
array: InvertPatternInternal<subpattern, ReadonlyArrayValue<input>>[];
|
|
36
|
+
record: subpattern extends [infer pk, infer pv] ? Record<Extract<InvertPatternInternal<pk, RecordKey<input>>, PropertyKey>, InvertPatternInternal<pv, RecordValue<input>>> : never;
|
|
37
|
+
map: subpattern extends [infer pk, infer pv] ? Map<InvertPatternInternal<pk, MapKey<Extract<input, Map<any, any>>>>, InvertPatternInternal<pv, MapValue<Extract<input, Map<any, any>>>>> : never;
|
|
38
|
+
set: Set<InvertPatternInternal<subpattern, SetValue<Extract<input, Set<any>>>>>;
|
|
39
|
+
optional: InvertPatternInternal<subpattern, Exclude<input, undefined>> | undefined;
|
|
40
|
+
and: ReduceIntersection<Extract<subpattern, readonly any[]>, input>;
|
|
41
|
+
or: ReduceUnion<Extract<subpattern, readonly any[]>, input>;
|
|
42
|
+
default: [subpattern] extends [never] ? input : subpattern;
|
|
43
|
+
custom: Override<narrowedOrFn extends Fn ? Call<narrowedOrFn, input> : narrowedOrFn>;
|
|
44
|
+
}[matcherType] : p extends Primitives ? p : p extends readonly any[] ? InvertArrayPattern<p, WithDefault<Extract<input, readonly any[]>, unknown[]>> : IsPlainObject<p> extends true ? OptionalKeys<p> extends infer optKeys ? [optKeys] extends [never] ? {
|
|
45
|
+
[k in Exclude<keyof p, optKeys>]: InvertPatternInternal<p[k], WithDefault<GetKey<ExtractPlainObject<input>, k>, unknown>>;
|
|
46
|
+
} : Compute<{
|
|
47
|
+
[k in Exclude<keyof p, optKeys>]: InvertPatternInternal<p[k], WithDefault<GetKey<ExtractPlainObject<input>, k>, unknown>>;
|
|
48
|
+
} & {
|
|
49
|
+
[k in Extract<optKeys, keyof p>]?: InvertPatternInternal<p[k], WithDefault<GetKey<ExtractPlainObject<input>, k>, unknown>>;
|
|
50
|
+
}> : never : p;
|
|
51
|
+
export type ReduceIntersectionForExclude<tuple extends readonly any[], i, output = unknown> = tuple extends readonly [infer p, ...infer tail] ? ReduceIntersectionForExclude<tail, i, output & InvertPatternForExcludeInternal<p, i, unknown>> : output;
|
|
52
|
+
export type ReduceUnionForExclude<tuple extends readonly any[], i, output = never> = tuple extends readonly [infer p, ...infer tail] ? ReduceUnionForExclude<tail, i, output | InvertPatternForExcludeInternal<p, i, never>> : output;
|
|
53
|
+
type ExcludeIfExists<a, b> = [
|
|
54
|
+
b
|
|
55
|
+
] extends [never] ? never : unknown extends a ? never : All<[
|
|
56
|
+
Extends<a, NonLiteralPrimitive>,
|
|
57
|
+
Not<IsLiteral<a>>,
|
|
58
|
+
IsLiteral<b>
|
|
59
|
+
]> extends true ? never : DeepExclude<a, b>;
|
|
60
|
+
type InvertArrayPatternForExclude<p, i, empty, isReadonly extends boolean, startOutput extends any[] = [], endOutput extends any[] = []> = i extends readonly (infer ii)[] ? p extends readonly [] ? MaybeAddReadonly<[...startOutput, ...endOutput], isReadonly> : p extends readonly [infer p1, ...infer pRest] ? i extends readonly [infer i1, ...infer iRest] ? InvertArrayPatternForExclude<pRest, iRest, empty, isReadonly, [
|
|
61
|
+
...startOutput,
|
|
62
|
+
InvertPatternForExcludeInternal<p1, i1, empty>
|
|
63
|
+
], endOutput> : InvertArrayPatternForExclude<pRest, ii[], empty, isReadonly, [
|
|
64
|
+
...startOutput,
|
|
65
|
+
InvertPatternForExcludeInternal<p1, ii, empty>
|
|
66
|
+
], endOutput> : p extends readonly [...infer pInit, infer p1] ? i extends readonly [...infer iInit, infer i1] ? InvertArrayPatternForExclude<pInit, iInit, empty, isReadonly, startOutput, [
|
|
67
|
+
...endOutput,
|
|
68
|
+
InvertPatternForExcludeInternal<p1, i1, empty>
|
|
69
|
+
]> : InvertArrayPatternForExclude<pInit, ii[], empty, isReadonly, startOutput, [
|
|
70
|
+
...endOutput,
|
|
71
|
+
InvertPatternForExcludeInternal<p1, ii, empty>
|
|
72
|
+
]> : p extends readonly [...(readonly (infer pRest & AnyMatcher)[])] ? MaybeAddReadonly<[
|
|
73
|
+
...startOutput,
|
|
74
|
+
...Extract<InvertPatternForExcludeInternal<pRest, i, empty>, readonly any[]>,
|
|
75
|
+
...endOutput
|
|
76
|
+
], isReadonly> : MaybeAddReadonly<[
|
|
77
|
+
...startOutput,
|
|
78
|
+
...InvertPatternForExcludeInternal<ValueOf<p>, ii, empty>[],
|
|
79
|
+
...endOutput
|
|
80
|
+
], isReadonly> : empty;
|
|
81
|
+
/**
|
|
82
|
+
* ### InvertPatternForExclude
|
|
83
|
+
*/
|
|
84
|
+
export type InvertPatternForExclude<p, i> = Equal<Pattern<i>, p> extends true ? never : InvertPatternForExcludeInternal<p, i>;
|
|
85
|
+
type InvertPatternForExcludeInternal<p, i, empty = never> = unknown extends p ? i : [p] extends [Primitives] ? IsLiteral<p> extends true ? p : IsLiteral<i> extends true ? p : empty : p extends Matcher<infer matchableInput, infer subpattern, infer matcherType, any, infer excluded> ? {
|
|
86
|
+
select: InvertPatternForExcludeInternal<subpattern, i, empty>;
|
|
87
|
+
array: i extends readonly (infer ii)[] ? MaybeAddReadonly<InvertPatternForExcludeInternal<subpattern, ii, empty>[], IsReadonlyArray<i>> : empty;
|
|
88
|
+
record: subpattern extends [infer pk, infer pv] ? Record<Extract<InvertPatternForExcludeInternal<pk, RecordKey<i>, empty>, PropertyKey>, InvertPatternForExcludeInternal<pv, RecordValue<i>, empty>> : empty;
|
|
89
|
+
map: subpattern extends [infer pk, infer pv] ? i extends Map<infer ik, infer iv> ? Map<InvertPatternForExcludeInternal<pk, ik, empty>, InvertPatternForExcludeInternal<pv, iv, empty>> : empty : empty;
|
|
90
|
+
set: i extends Set<infer iv> ? Set<InvertPatternForExcludeInternal<subpattern, iv, empty>> : empty;
|
|
91
|
+
optional: InvertPatternForExcludeInternal<subpattern, i, empty> | undefined;
|
|
92
|
+
and: ReduceIntersectionForExclude<Extract<subpattern, readonly any[]>, i>;
|
|
93
|
+
or: ReduceUnionForExclude<Extract<subpattern, readonly any[]>, i>;
|
|
94
|
+
not: ExcludeIfExists<unknown extends matchableInput ? i : matchableInput, InvertPatternForExcludeInternal<subpattern, i>>;
|
|
95
|
+
default: excluded;
|
|
96
|
+
custom: excluded extends infer narrowedOrFn extends Fn ? Call<narrowedOrFn, i> : excluded;
|
|
97
|
+
}[matcherType] : p extends readonly any[] ? Extract<i, readonly any[]> extends infer arrayInput ? InvertArrayPatternForExclude<p, arrayInput, empty, IsReadonlyArray<arrayInput>> : never : IsPlainObject<p> extends true ? Equal<{}, p> extends true ? {} : i extends object ? [keyof p & keyof i] extends [never] ? empty : OptionalKeys<p> extends infer optKeys ? [optKeys] extends [never] ? {
|
|
98
|
+
readonly [k in keyof p]: k extends keyof i ? InvertPatternForExcludeInternal<p[k], i[k], empty> : InvertPatternInternal<p[k], unknown>;
|
|
99
|
+
} : Compute<{
|
|
100
|
+
readonly [k in Exclude<keyof p, optKeys>]: k extends keyof i ? InvertPatternForExcludeInternal<p[k], i[k], empty> : InvertPatternInternal<p[k], unknown>;
|
|
101
|
+
} & {
|
|
102
|
+
readonly [k in Extract<optKeys, keyof p>]?: k extends keyof i ? InvertPatternForExcludeInternal<p[k], i[k], empty> : InvertPatternInternal<p[k], unknown>;
|
|
103
|
+
}> : empty : empty : empty;
|
|
104
|
+
export {};
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { Primitives, IsPlainObject, IsUnion, ValueOf, Length, IsLiteral, All, Equal } from './helpers.cjs';
|
|
2
|
+
type IsMatchingTuple<a extends readonly any[], b extends readonly any[]> = [
|
|
3
|
+
a,
|
|
4
|
+
b
|
|
5
|
+
] extends [readonly [], readonly []] ? true : [a, b] extends [
|
|
6
|
+
readonly [infer a1, ...infer aRest],
|
|
7
|
+
readonly [infer b1, ...infer bRest]
|
|
8
|
+
] ? IsMatching<a1, b1> extends true ? IsMatchingTuple<aRest, bRest> : false : false;
|
|
9
|
+
type IsMatchingArray<a extends readonly any[], b extends readonly any[]> = b extends readonly [] ? true : b extends readonly [infer b1, ...infer bRest] ? a extends readonly [infer a1, ...infer aRest] ? IsMatching<a1, b1> extends true ? IsMatchingArray<aRest, bRest> : false : a extends readonly [] ? false : IsMatching<ValueOf<a>, b1> extends true ? IsMatchingArray<a, bRest> : false : b extends readonly [...infer bInit, infer b1] ? a extends readonly [...infer aInit, infer a1] ? IsMatching<a1, b1> extends true ? IsMatchingArray<aInit, bInit> : false : a extends readonly [] ? false : IsMatching<ValueOf<a>, b1> extends true ? IsMatchingArray<a, bInit> : false : IsMatching<ValueOf<a>, ValueOf<b>>;
|
|
10
|
+
export type IsMatching<a, b> = true extends IsUnion<a> | IsUnion<b> ? true extends (b extends any ? (a extends any ? IsMatching<a, b> : never) : never) ? true : false : unknown extends b ? true : {} extends b ? true : b extends Primitives ? a extends b ? true : b extends a ? true : false : Equal<a, b> extends true ? true : b extends readonly any[] ? a extends readonly any[] ? All<[IsLiteral<Length<a>>, IsLiteral<Length<b>>]> extends true ? Equal<Length<a>, Length<b>> extends false ? false : IsMatchingTuple<a, b> : IsMatchingArray<a, b> : false : IsPlainObject<b> extends true ? true extends (a extends any ? [keyof b & keyof a] extends [never] ? false : {
|
|
11
|
+
[k in keyof b & keyof a]: IsMatching<a[k], b[k]>;
|
|
12
|
+
}[keyof b & keyof a] extends true ? true : false : never) ? true : false : b extends a ? true : false;
|
|
13
|
+
export {};
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { Primitives, IsPlainObject, IsUnion, ValueOf, Length, IsLiteral, All, Equal } from './helpers.js';
|
|
2
|
+
type IsMatchingTuple<a extends readonly any[], b extends readonly any[]> = [
|
|
3
|
+
a,
|
|
4
|
+
b
|
|
5
|
+
] extends [readonly [], readonly []] ? true : [a, b] extends [
|
|
6
|
+
readonly [infer a1, ...infer aRest],
|
|
7
|
+
readonly [infer b1, ...infer bRest]
|
|
8
|
+
] ? IsMatching<a1, b1> extends true ? IsMatchingTuple<aRest, bRest> : false : false;
|
|
9
|
+
type IsMatchingArray<a extends readonly any[], b extends readonly any[]> = b extends readonly [] ? true : b extends readonly [infer b1, ...infer bRest] ? a extends readonly [infer a1, ...infer aRest] ? IsMatching<a1, b1> extends true ? IsMatchingArray<aRest, bRest> : false : a extends readonly [] ? false : IsMatching<ValueOf<a>, b1> extends true ? IsMatchingArray<a, bRest> : false : b extends readonly [...infer bInit, infer b1] ? a extends readonly [...infer aInit, infer a1] ? IsMatching<a1, b1> extends true ? IsMatchingArray<aInit, bInit> : false : a extends readonly [] ? false : IsMatching<ValueOf<a>, b1> extends true ? IsMatchingArray<a, bInit> : false : IsMatching<ValueOf<a>, ValueOf<b>>;
|
|
10
|
+
export type IsMatching<a, b> = true extends IsUnion<a> | IsUnion<b> ? true extends (b extends any ? (a extends any ? IsMatching<a, b> : never) : never) ? true : false : unknown extends b ? true : {} extends b ? true : b extends Primitives ? a extends b ? true : b extends a ? true : false : Equal<a, b> extends true ? true : b extends readonly any[] ? a extends readonly any[] ? All<[IsLiteral<Length<a>>, IsLiteral<Length<b>>]> extends true ? Equal<Length<a>, Length<b>> extends false ? false : IsMatchingTuple<a, b> : IsMatchingArray<a, b> : false : IsPlainObject<b> extends true ? true extends (a extends any ? [keyof b & keyof a] extends [never] ? false : {
|
|
11
|
+
[k in keyof b & keyof a]: IsMatching<a[k], b[k]>;
|
|
12
|
+
}[keyof b & keyof a] extends true ? true : false : never) ? true : false : b extends a ? true : false;
|
|
13
|
+
export {};
|
|
@@ -0,0 +1,171 @@
|
|
|
1
|
+
import type * as symbols from '../internals/symbols.cjs';
|
|
2
|
+
import type { Pattern, MatchedValue } from './Pattern.cjs';
|
|
3
|
+
import type { InvertPatternForExclude, InvertPattern } from './InvertPattern.cjs';
|
|
4
|
+
import type { DeepExclude } from './DeepExclude.cjs';
|
|
5
|
+
import type { Union, GuardValue, IsNever } from './helpers.cjs';
|
|
6
|
+
import type { FindSelected } from './FindSelected.cjs';
|
|
7
|
+
export type PickReturnValue<a, b> = a extends symbols.unset ? b : a;
|
|
8
|
+
interface NonExhaustiveError<i> {
|
|
9
|
+
__nonExhaustive: never;
|
|
10
|
+
}
|
|
11
|
+
interface TSPatternError<i> {
|
|
12
|
+
__nonExhaustive: never;
|
|
13
|
+
}
|
|
14
|
+
/**
|
|
15
|
+
* #### Match
|
|
16
|
+
* An interface to create a pattern matching clause.
|
|
17
|
+
*/
|
|
18
|
+
export type Match<i, o, handledCases extends any[] = [], inferredOutput = never> = {
|
|
19
|
+
/**
|
|
20
|
+
* `.with(pattern, handler)` Registers a pattern and an handler function that
|
|
21
|
+
* will be called if the pattern matches the input value.
|
|
22
|
+
*
|
|
23
|
+
* [Read the documentation for `.with()` on GitHub](https://github.com/gvergnaud/ts-pattern#with)
|
|
24
|
+
**/
|
|
25
|
+
with<const p extends Pattern<i>, c, value extends MatchedValue<i, InvertPattern<p, i>>>(pattern: IsNever<p> extends true ? Pattern<i> : p, handler: (selections: FindSelected<value, p>, value: value) => PickReturnValue<o, c>): InvertPatternForExclude<p, value> extends infer excluded ? Match<Exclude<i, excluded>, o, [
|
|
26
|
+
...handledCases,
|
|
27
|
+
excluded
|
|
28
|
+
], Union<inferredOutput, c>> : never;
|
|
29
|
+
with<const p1 extends Pattern<i>, const p2 extends Pattern<i>, c, p extends p1 | p2, value extends p extends any ? MatchedValue<i, InvertPattern<p, i>> : never>(p1: p1, p2: p2, handler: (value: value) => PickReturnValue<o, c>): [
|
|
30
|
+
InvertPatternForExclude<p1, value>,
|
|
31
|
+
InvertPatternForExclude<p2, value>
|
|
32
|
+
] extends [infer excluded1, infer excluded2] ? Match<Exclude<i, excluded1 | excluded2>, o, [
|
|
33
|
+
...handledCases,
|
|
34
|
+
excluded1,
|
|
35
|
+
excluded2
|
|
36
|
+
], Union<inferredOutput, c>> : never;
|
|
37
|
+
with<const p1 extends Pattern<i>, const p2 extends Pattern<i>, const p3 extends Pattern<i>, const ps extends readonly Pattern<i>[], c, p extends p1 | p2 | p3 | ps[number], value extends MatchedValue<i, InvertPattern<p, i>>>(...args: [
|
|
38
|
+
p1: p1,
|
|
39
|
+
p2: p2,
|
|
40
|
+
p3: p3,
|
|
41
|
+
...patterns: ps,
|
|
42
|
+
handler: (value: value) => PickReturnValue<o, c>
|
|
43
|
+
]): [
|
|
44
|
+
InvertPatternForExclude<p1, value>,
|
|
45
|
+
InvertPatternForExclude<p2, value>,
|
|
46
|
+
InvertPatternForExclude<p3, value>,
|
|
47
|
+
MakeTuples<ps, value>
|
|
48
|
+
] extends [
|
|
49
|
+
infer excluded1,
|
|
50
|
+
infer excluded2,
|
|
51
|
+
infer excluded3,
|
|
52
|
+
infer excludedRest
|
|
53
|
+
] ? Match<Exclude<i, excluded1 | excluded2 | excluded3 | Extract<excludedRest, any[]>[number]>, o, [
|
|
54
|
+
...handledCases,
|
|
55
|
+
excluded1,
|
|
56
|
+
excluded2,
|
|
57
|
+
excluded3,
|
|
58
|
+
...Extract<excludedRest, any[]>
|
|
59
|
+
], Union<inferredOutput, c>> : never;
|
|
60
|
+
with<const pat extends Pattern<i>, pred extends (value: MatchedValue<i, InvertPattern<pat, i>>) => unknown, c, value extends GuardValue<pred>>(pattern: pat, predicate: pred, handler: (selections: FindSelected<value, pat>, value: value) => PickReturnValue<o, c>): pred extends (value: any) => value is infer narrowed ? Match<Exclude<i, narrowed>, o, [
|
|
61
|
+
...handledCases,
|
|
62
|
+
narrowed
|
|
63
|
+
], Union<inferredOutput, c>> : Match<i, o, handledCases, Union<inferredOutput, c>>;
|
|
64
|
+
/**
|
|
65
|
+
* `.when(predicate, handler)` Registers a predicate function and an handler function.
|
|
66
|
+
* If the predicate returns true, the handler function will be called.
|
|
67
|
+
*
|
|
68
|
+
* [Read the documentation for `.when()` on GitHub](https://github.com/gvergnaud/ts-pattern#when)
|
|
69
|
+
**/
|
|
70
|
+
when<pred extends (value: i) => unknown, c, value extends GuardValue<pred>>(predicate: pred, handler: (value: value) => PickReturnValue<o, c>): pred extends (value: any) => value is infer narrowed ? Match<Exclude<i, narrowed>, o, [
|
|
71
|
+
...handledCases,
|
|
72
|
+
narrowed
|
|
73
|
+
], Union<inferredOutput, c>> : Match<i, o, handledCases, Union<inferredOutput, c>>;
|
|
74
|
+
/**
|
|
75
|
+
* `.otherwise()` takes a **default handler function** that will be
|
|
76
|
+
* called if no previous pattern matched your input.
|
|
77
|
+
*
|
|
78
|
+
* Equivalent to `.with(P._, () => x).exhaustive()`
|
|
79
|
+
*
|
|
80
|
+
* [Read the documentation for `.otherwise()` on GitHub](https://github.com/gvergnaud/ts-pattern#otherwise)
|
|
81
|
+
*
|
|
82
|
+
**/
|
|
83
|
+
otherwise<c>(handler: (value: i) => PickReturnValue<o, c>): PickReturnValue<o, Union<inferredOutput, c>>;
|
|
84
|
+
/**
|
|
85
|
+
* `.exhaustive()` checks that all cases are handled, and returns the result value.
|
|
86
|
+
*
|
|
87
|
+
* If you get a `NonExhaustiveError`, it means that you aren't handling
|
|
88
|
+
* all cases. You should probably add another `.with(...)` clause
|
|
89
|
+
* to match the missing case and prevent runtime errors.
|
|
90
|
+
*
|
|
91
|
+
* [Read the documentation for `.exhaustive()` on GitHub](https://github.com/gvergnaud/ts-pattern#exhaustive)
|
|
92
|
+
*
|
|
93
|
+
*/
|
|
94
|
+
exhaustive: DeepExcludeAll<i, handledCases> extends infer remainingCases ? [remainingCases] extends [never] ? Exhaustive<o, inferredOutput> : NonExhaustiveError<remainingCases> : never;
|
|
95
|
+
/**
|
|
96
|
+
* `.run()` return the resulting value.
|
|
97
|
+
*
|
|
98
|
+
* ⚠️ calling this function is unsafe, and may throw if no pattern matches your input.
|
|
99
|
+
*/
|
|
100
|
+
run(): PickReturnValue<o, inferredOutput>;
|
|
101
|
+
/**
|
|
102
|
+
* `.returnType<T>()` Lets you specify the return type for all of your branches.
|
|
103
|
+
*
|
|
104
|
+
* [Read the documentation for `.returnType()` on GitHub](https://github.com/gvergnaud/ts-pattern#returnType)
|
|
105
|
+
*/
|
|
106
|
+
returnType: [inferredOutput] extends [never] ? <output>() => Match<i, output, handledCases> : TSPatternError<'calling `.returnType<T>()` is only allowed directly after `match(...)`.'>;
|
|
107
|
+
/**
|
|
108
|
+
* `.narrow()` narrows the input type to exclude all cases that have previously been handled.
|
|
109
|
+
*
|
|
110
|
+
* `.narrow()` is only useful if you want to excluded cases from union types or nullable
|
|
111
|
+
* properties that are deeply nested. Handled cases from top level union types are excluded
|
|
112
|
+
* by default.
|
|
113
|
+
*
|
|
114
|
+
* [Read the documentation for `.narrow() on GitHub](https://github.com/gvergnaud/ts-pattern#narrow)
|
|
115
|
+
*/
|
|
116
|
+
narrow(): Match<DeepExcludeAll<i, handledCases>, o, [], inferredOutput>;
|
|
117
|
+
};
|
|
118
|
+
/**
|
|
119
|
+
* Potential for optimization here:
|
|
120
|
+
*
|
|
121
|
+
* Since DeepExclude distributes the union of the input type, it can
|
|
122
|
+
* generate very large union types on patterns touching several unions at once.
|
|
123
|
+
* If we were sorting patterns from those which distribute the smallest
|
|
124
|
+
* amount of union types to those which distribute the largest, we would eliminate
|
|
125
|
+
* cheap cases more quickly and have less cases in the input type for patterns
|
|
126
|
+
* that will be expensive to exclude.
|
|
127
|
+
*
|
|
128
|
+
* This pre supposes that we have a cheap way of telling if the number
|
|
129
|
+
* of union types a pattern touches and a cheap way of sorting the tuple
|
|
130
|
+
* of patterns.
|
|
131
|
+
* - For the first part, we could reuse `FindMatchingUnions` and pick the `length`
|
|
132
|
+
* of the returned tuple.
|
|
133
|
+
* - For the second part though I'm not aware a cheap way of sorting a tuple.
|
|
134
|
+
*/
|
|
135
|
+
type DeepExcludeAll<a, tupleList extends any[]> = [a] extends [never] ? never : tupleList extends [infer excluded, ...infer tail] ? DeepExcludeAll<DeepExclude<a, excluded>, tail> : a;
|
|
136
|
+
type MakeTuples<ps extends readonly any[], value> = {
|
|
137
|
+
-readonly [index in keyof ps]: InvertPatternForExclude<ps[index], value>;
|
|
138
|
+
};
|
|
139
|
+
/**
|
|
140
|
+
* The type of an overloaded function for `.exhaustive`,
|
|
141
|
+
* permitting calling it with or without a catch-all handler function.
|
|
142
|
+
*
|
|
143
|
+
* By default, TS-Pattern will throw an error if a runtime value isn't handled.
|
|
144
|
+
*/
|
|
145
|
+
type Exhaustive<output, inferredOutput> = {
|
|
146
|
+
/**
|
|
147
|
+
* `.exhaustive()` checks that all cases are handled, and returns the result value.
|
|
148
|
+
*
|
|
149
|
+
* If you get a `NonExhaustiveError`, it means that you aren't handling
|
|
150
|
+
* all cases. You should probably add another `.with(...)` clause
|
|
151
|
+
* to match the missing case and prevent runtime errors.
|
|
152
|
+
*
|
|
153
|
+
* [Read the documentation for `.exhaustive()` on GitHub](https://github.com/gvergnaud/ts-pattern#exhaustive)
|
|
154
|
+
*
|
|
155
|
+
*/
|
|
156
|
+
(): PickReturnValue<output, inferredOutput>;
|
|
157
|
+
/**
|
|
158
|
+
* `.exhaustive(fallback)` checks that all cases are handled and returns the result value.
|
|
159
|
+
*
|
|
160
|
+
* The fallback function will be called if your input value doesn't match any pattern.
|
|
161
|
+
* This can only happen if the value you passed to `match` has an incorrect type.
|
|
162
|
+
*
|
|
163
|
+
* If you get a `NonExhaustiveError`, it means that you aren't handling
|
|
164
|
+
* all cases. You should probably add another `.with(...)` clause
|
|
165
|
+
* to match the missing case.
|
|
166
|
+
*
|
|
167
|
+
* [Read the documentation for `.exhaustive()` on GitHub](https://github.com/gvergnaud/ts-pattern#exhaustive)
|
|
168
|
+
*/
|
|
169
|
+
<otherOutput>(handler: (unexpectedValue: unknown) => PickReturnValue<output, otherOutput>): PickReturnValue<output, Union<inferredOutput, otherOutput>>;
|
|
170
|
+
};
|
|
171
|
+
export {};
|
|
@@ -0,0 +1,171 @@
|
|
|
1
|
+
import type * as symbols from '../internals/symbols.js';
|
|
2
|
+
import type { Pattern, MatchedValue } from './Pattern.js';
|
|
3
|
+
import type { InvertPatternForExclude, InvertPattern } from './InvertPattern.js';
|
|
4
|
+
import type { DeepExclude } from './DeepExclude.js';
|
|
5
|
+
import type { Union, GuardValue, IsNever } from './helpers.js';
|
|
6
|
+
import type { FindSelected } from './FindSelected.js';
|
|
7
|
+
export type PickReturnValue<a, b> = a extends symbols.unset ? b : a;
|
|
8
|
+
interface NonExhaustiveError<i> {
|
|
9
|
+
__nonExhaustive: never;
|
|
10
|
+
}
|
|
11
|
+
interface TSPatternError<i> {
|
|
12
|
+
__nonExhaustive: never;
|
|
13
|
+
}
|
|
14
|
+
/**
|
|
15
|
+
* #### Match
|
|
16
|
+
* An interface to create a pattern matching clause.
|
|
17
|
+
*/
|
|
18
|
+
export type Match<i, o, handledCases extends any[] = [], inferredOutput = never> = {
|
|
19
|
+
/**
|
|
20
|
+
* `.with(pattern, handler)` Registers a pattern and an handler function that
|
|
21
|
+
* will be called if the pattern matches the input value.
|
|
22
|
+
*
|
|
23
|
+
* [Read the documentation for `.with()` on GitHub](https://github.com/gvergnaud/ts-pattern#with)
|
|
24
|
+
**/
|
|
25
|
+
with<const p extends Pattern<i>, c, value extends MatchedValue<i, InvertPattern<p, i>>>(pattern: IsNever<p> extends true ? Pattern<i> : p, handler: (selections: FindSelected<value, p>, value: value) => PickReturnValue<o, c>): InvertPatternForExclude<p, value> extends infer excluded ? Match<Exclude<i, excluded>, o, [
|
|
26
|
+
...handledCases,
|
|
27
|
+
excluded
|
|
28
|
+
], Union<inferredOutput, c>> : never;
|
|
29
|
+
with<const p1 extends Pattern<i>, const p2 extends Pattern<i>, c, p extends p1 | p2, value extends p extends any ? MatchedValue<i, InvertPattern<p, i>> : never>(p1: p1, p2: p2, handler: (value: value) => PickReturnValue<o, c>): [
|
|
30
|
+
InvertPatternForExclude<p1, value>,
|
|
31
|
+
InvertPatternForExclude<p2, value>
|
|
32
|
+
] extends [infer excluded1, infer excluded2] ? Match<Exclude<i, excluded1 | excluded2>, o, [
|
|
33
|
+
...handledCases,
|
|
34
|
+
excluded1,
|
|
35
|
+
excluded2
|
|
36
|
+
], Union<inferredOutput, c>> : never;
|
|
37
|
+
with<const p1 extends Pattern<i>, const p2 extends Pattern<i>, const p3 extends Pattern<i>, const ps extends readonly Pattern<i>[], c, p extends p1 | p2 | p3 | ps[number], value extends MatchedValue<i, InvertPattern<p, i>>>(...args: [
|
|
38
|
+
p1: p1,
|
|
39
|
+
p2: p2,
|
|
40
|
+
p3: p3,
|
|
41
|
+
...patterns: ps,
|
|
42
|
+
handler: (value: value) => PickReturnValue<o, c>
|
|
43
|
+
]): [
|
|
44
|
+
InvertPatternForExclude<p1, value>,
|
|
45
|
+
InvertPatternForExclude<p2, value>,
|
|
46
|
+
InvertPatternForExclude<p3, value>,
|
|
47
|
+
MakeTuples<ps, value>
|
|
48
|
+
] extends [
|
|
49
|
+
infer excluded1,
|
|
50
|
+
infer excluded2,
|
|
51
|
+
infer excluded3,
|
|
52
|
+
infer excludedRest
|
|
53
|
+
] ? Match<Exclude<i, excluded1 | excluded2 | excluded3 | Extract<excludedRest, any[]>[number]>, o, [
|
|
54
|
+
...handledCases,
|
|
55
|
+
excluded1,
|
|
56
|
+
excluded2,
|
|
57
|
+
excluded3,
|
|
58
|
+
...Extract<excludedRest, any[]>
|
|
59
|
+
], Union<inferredOutput, c>> : never;
|
|
60
|
+
with<const pat extends Pattern<i>, pred extends (value: MatchedValue<i, InvertPattern<pat, i>>) => unknown, c, value extends GuardValue<pred>>(pattern: pat, predicate: pred, handler: (selections: FindSelected<value, pat>, value: value) => PickReturnValue<o, c>): pred extends (value: any) => value is infer narrowed ? Match<Exclude<i, narrowed>, o, [
|
|
61
|
+
...handledCases,
|
|
62
|
+
narrowed
|
|
63
|
+
], Union<inferredOutput, c>> : Match<i, o, handledCases, Union<inferredOutput, c>>;
|
|
64
|
+
/**
|
|
65
|
+
* `.when(predicate, handler)` Registers a predicate function and an handler function.
|
|
66
|
+
* If the predicate returns true, the handler function will be called.
|
|
67
|
+
*
|
|
68
|
+
* [Read the documentation for `.when()` on GitHub](https://github.com/gvergnaud/ts-pattern#when)
|
|
69
|
+
**/
|
|
70
|
+
when<pred extends (value: i) => unknown, c, value extends GuardValue<pred>>(predicate: pred, handler: (value: value) => PickReturnValue<o, c>): pred extends (value: any) => value is infer narrowed ? Match<Exclude<i, narrowed>, o, [
|
|
71
|
+
...handledCases,
|
|
72
|
+
narrowed
|
|
73
|
+
], Union<inferredOutput, c>> : Match<i, o, handledCases, Union<inferredOutput, c>>;
|
|
74
|
+
/**
|
|
75
|
+
* `.otherwise()` takes a **default handler function** that will be
|
|
76
|
+
* called if no previous pattern matched your input.
|
|
77
|
+
*
|
|
78
|
+
* Equivalent to `.with(P._, () => x).exhaustive()`
|
|
79
|
+
*
|
|
80
|
+
* [Read the documentation for `.otherwise()` on GitHub](https://github.com/gvergnaud/ts-pattern#otherwise)
|
|
81
|
+
*
|
|
82
|
+
**/
|
|
83
|
+
otherwise<c>(handler: (value: i) => PickReturnValue<o, c>): PickReturnValue<o, Union<inferredOutput, c>>;
|
|
84
|
+
/**
|
|
85
|
+
* `.exhaustive()` checks that all cases are handled, and returns the result value.
|
|
86
|
+
*
|
|
87
|
+
* If you get a `NonExhaustiveError`, it means that you aren't handling
|
|
88
|
+
* all cases. You should probably add another `.with(...)` clause
|
|
89
|
+
* to match the missing case and prevent runtime errors.
|
|
90
|
+
*
|
|
91
|
+
* [Read the documentation for `.exhaustive()` on GitHub](https://github.com/gvergnaud/ts-pattern#exhaustive)
|
|
92
|
+
*
|
|
93
|
+
*/
|
|
94
|
+
exhaustive: DeepExcludeAll<i, handledCases> extends infer remainingCases ? [remainingCases] extends [never] ? Exhaustive<o, inferredOutput> : NonExhaustiveError<remainingCases> : never;
|
|
95
|
+
/**
|
|
96
|
+
* `.run()` return the resulting value.
|
|
97
|
+
*
|
|
98
|
+
* ⚠️ calling this function is unsafe, and may throw if no pattern matches your input.
|
|
99
|
+
*/
|
|
100
|
+
run(): PickReturnValue<o, inferredOutput>;
|
|
101
|
+
/**
|
|
102
|
+
* `.returnType<T>()` Lets you specify the return type for all of your branches.
|
|
103
|
+
*
|
|
104
|
+
* [Read the documentation for `.returnType()` on GitHub](https://github.com/gvergnaud/ts-pattern#returnType)
|
|
105
|
+
*/
|
|
106
|
+
returnType: [inferredOutput] extends [never] ? <output>() => Match<i, output, handledCases> : TSPatternError<'calling `.returnType<T>()` is only allowed directly after `match(...)`.'>;
|
|
107
|
+
/**
|
|
108
|
+
* `.narrow()` narrows the input type to exclude all cases that have previously been handled.
|
|
109
|
+
*
|
|
110
|
+
* `.narrow()` is only useful if you want to excluded cases from union types or nullable
|
|
111
|
+
* properties that are deeply nested. Handled cases from top level union types are excluded
|
|
112
|
+
* by default.
|
|
113
|
+
*
|
|
114
|
+
* [Read the documentation for `.narrow() on GitHub](https://github.com/gvergnaud/ts-pattern#narrow)
|
|
115
|
+
*/
|
|
116
|
+
narrow(): Match<DeepExcludeAll<i, handledCases>, o, [], inferredOutput>;
|
|
117
|
+
};
|
|
118
|
+
/**
|
|
119
|
+
* Potential for optimization here:
|
|
120
|
+
*
|
|
121
|
+
* Since DeepExclude distributes the union of the input type, it can
|
|
122
|
+
* generate very large union types on patterns touching several unions at once.
|
|
123
|
+
* If we were sorting patterns from those which distribute the smallest
|
|
124
|
+
* amount of union types to those which distribute the largest, we would eliminate
|
|
125
|
+
* cheap cases more quickly and have less cases in the input type for patterns
|
|
126
|
+
* that will be expensive to exclude.
|
|
127
|
+
*
|
|
128
|
+
* This pre supposes that we have a cheap way of telling if the number
|
|
129
|
+
* of union types a pattern touches and a cheap way of sorting the tuple
|
|
130
|
+
* of patterns.
|
|
131
|
+
* - For the first part, we could reuse `FindMatchingUnions` and pick the `length`
|
|
132
|
+
* of the returned tuple.
|
|
133
|
+
* - For the second part though I'm not aware a cheap way of sorting a tuple.
|
|
134
|
+
*/
|
|
135
|
+
type DeepExcludeAll<a, tupleList extends any[]> = [a] extends [never] ? never : tupleList extends [infer excluded, ...infer tail] ? DeepExcludeAll<DeepExclude<a, excluded>, tail> : a;
|
|
136
|
+
type MakeTuples<ps extends readonly any[], value> = {
|
|
137
|
+
-readonly [index in keyof ps]: InvertPatternForExclude<ps[index], value>;
|
|
138
|
+
};
|
|
139
|
+
/**
|
|
140
|
+
* The type of an overloaded function for `.exhaustive`,
|
|
141
|
+
* permitting calling it with or without a catch-all handler function.
|
|
142
|
+
*
|
|
143
|
+
* By default, TS-Pattern will throw an error if a runtime value isn't handled.
|
|
144
|
+
*/
|
|
145
|
+
type Exhaustive<output, inferredOutput> = {
|
|
146
|
+
/**
|
|
147
|
+
* `.exhaustive()` checks that all cases are handled, and returns the result value.
|
|
148
|
+
*
|
|
149
|
+
* If you get a `NonExhaustiveError`, it means that you aren't handling
|
|
150
|
+
* all cases. You should probably add another `.with(...)` clause
|
|
151
|
+
* to match the missing case and prevent runtime errors.
|
|
152
|
+
*
|
|
153
|
+
* [Read the documentation for `.exhaustive()` on GitHub](https://github.com/gvergnaud/ts-pattern#exhaustive)
|
|
154
|
+
*
|
|
155
|
+
*/
|
|
156
|
+
(): PickReturnValue<output, inferredOutput>;
|
|
157
|
+
/**
|
|
158
|
+
* `.exhaustive(fallback)` checks that all cases are handled and returns the result value.
|
|
159
|
+
*
|
|
160
|
+
* The fallback function will be called if your input value doesn't match any pattern.
|
|
161
|
+
* This can only happen if the value you passed to `match` has an incorrect type.
|
|
162
|
+
*
|
|
163
|
+
* If you get a `NonExhaustiveError`, it means that you aren't handling
|
|
164
|
+
* all cases. You should probably add another `.with(...)` clause
|
|
165
|
+
* to match the missing case.
|
|
166
|
+
*
|
|
167
|
+
* [Read the documentation for `.exhaustive()` on GitHub](https://github.com/gvergnaud/ts-pattern#exhaustive)
|
|
168
|
+
*/
|
|
169
|
+
<otherOutput>(handler: (unexpectedValue: unknown) => PickReturnValue<output, otherOutput>): PickReturnValue<output, Union<inferredOutput, otherOutput>>;
|
|
170
|
+
};
|
|
171
|
+
export {};
|