@cuppachino/ts-pattern
Version:
The exhaustive Pattern Matching library for TypeScript.
92 lines (91 loc) • 6.77 kB
TypeScript
import { DeepExclude } from './DeepExclude.js';
import { IsPlainObject, Primitives, IsLiteral, ValueOf, Compute, Cast, Equal, Extends, Not, All, NonLiteralPrimitive } from './helpers.js';
import type { Matcher, Pattern, ToExclude } from './Pattern.js';
declare type OptionalKeys<p> = ValueOf<{
[k in keyof p]: p[k] extends Matcher<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;
/**
* ### InvertPattern
* Since patterns have special wildcard values, we need a way
* to transform a pattern into the type of value it represents
*/
export declare type InvertPattern<p> = p extends Matcher<infer input, infer narrowed, infer matcherType, any> ? {
not: ToExclude<InvertPattern<narrowed>>;
select: InvertPattern<narrowed>;
array: InvertPattern<narrowed>[];
optional: InvertPattern<narrowed> | undefined;
and: ReduceIntersection<Cast<narrowed, any[]>>;
or: ReduceUnion<Cast<narrowed, any[]>>;
default: [narrowed] extends [never] ? input : narrowed;
}[matcherType] : p extends Primitives ? p : p extends readonly (infer pp)[] ? p extends readonly [infer p1, infer p2, infer p3, infer p4, infer p5] ? [
InvertPattern<p1>,
InvertPattern<p2>,
InvertPattern<p3>,
InvertPattern<p4>,
InvertPattern<p5>
] : p extends readonly [infer p1, infer p2, infer p3, infer p4] ? [
InvertPattern<p1>,
InvertPattern<p2>,
InvertPattern<p3>,
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>] : 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 ? OptionalKeys<p> extends infer optKeys ? [optKeys] extends [never] ? {
[k in Exclude<keyof p, optKeys>]: InvertPattern<p[k]>;
} : Compute<{
[k in Exclude<keyof p, optKeys>]: InvertPattern<p[k]>;
} & {
[k in Cast<optKeys, keyof p>]?: InvertPattern<p[k]>;
}> : never : p;
export declare type ReduceIntersectionForExclude<tuple extends any[], i, output = unknown> = tuple extends readonly [infer p, ...infer tail] ? ReduceIntersectionForExclude<tail, i, output & InvertPatternForExcludeInternal<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 | InvertPatternForExcludeInternal<p, i, never>> : output;
declare type ExcludeIfExists<a, b> = [
b
] extends [never] ? never : unknown extends a ? never : All<[
Extends<a, NonLiteralPrimitive>,
Not<IsLiteral<a>>,
IsLiteral<b>
]> extends true ? never : DeepExclude<a, b>;
/**
* ### InvertPatternForExclude
*/
export declare type InvertPatternForExclude<p, i> = Equal<p, Pattern<i>> extends true ? never : InvertPatternForExcludeInternal<p, i>;
declare type InvertPatternForExcludeInternal<p, i, empty = never> = [
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> ? {
select: InvertPatternForExcludeInternal<subpattern, i, empty>;
array: i extends readonly (infer ii)[] ? InvertPatternForExcludeInternal<subpattern, ii, empty>[] : empty;
optional: InvertPatternForExcludeInternal<subpattern, i, empty> | undefined;
and: ReduceIntersectionForExclude<Cast<subpattern, any[]>, i>;
or: ReduceUnionForExclude<Cast<subpattern, any[]>, i>;
not: ExcludeIfExists<unknown extends matchableInput ? i : matchableInput, InvertPatternForExcludeInternal<subpattern, i>>;
default: excluded;
}[matcherType] : 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 [
InvertPatternForExcludeInternal<p1, i1, empty>,
InvertPatternForExcludeInternal<p2, i2, empty>,
InvertPatternForExcludeInternal<p3, i3, empty>,
InvertPatternForExcludeInternal<p4, i4, empty>,
InvertPatternForExcludeInternal<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 [
InvertPatternForExcludeInternal<p1, i1, empty>,
InvertPatternForExcludeInternal<p2, i2, empty>,
InvertPatternForExcludeInternal<p3, i3, empty>,
InvertPatternForExcludeInternal<p4, i4, empty>
] : empty : p extends readonly [infer p1, infer p2, infer p3] ? i extends readonly [infer i1, infer i2, infer i3] ? readonly [
InvertPatternForExcludeInternal<p1, i1, empty>,
InvertPatternForExcludeInternal<p2, i2, empty>,
InvertPatternForExcludeInternal<p3, i3, empty>
] : empty : p extends readonly [infer p1, infer p2] ? i extends readonly [infer i1, infer i2] ? readonly [
InvertPatternForExcludeInternal<p1, i1, empty>,
InvertPatternForExcludeInternal<p2, i2, empty>
] : empty : p extends readonly [infer p1] ? i extends readonly [infer i1] ? readonly [InvertPatternForExcludeInternal<p1, i1, empty>] : empty : p extends readonly [] ? [] : InvertPatternForExcludeInternal<pp, ii, empty>[] : empty : p extends Map<infer pk, infer pv> ? i extends Map<any, infer iv> ? Map<pk, InvertPatternForExcludeInternal<pv, iv, empty>> : empty : p extends Set<infer pv> ? i extends Set<infer iv> ? Set<InvertPatternForExcludeInternal<pv, iv, empty>> : empty : IsPlainObject<p> extends true ? i extends object ? [keyof p & keyof i] extends [never] ? empty : OptionalKeys<p> extends infer optKeys ? [optKeys] extends [never] ? {
readonly [k in keyof p]: k extends keyof i ? InvertPatternForExcludeInternal<p[k], i[k], empty> : InvertPattern<p[k]>;
} : Compute<{
readonly [k in Exclude<keyof p, optKeys>]: k extends keyof i ? InvertPatternForExcludeInternal<p[k], i[k], empty> : InvertPattern<p[k]>;
} & {
readonly [k in Cast<optKeys, keyof p>]?: k extends keyof i ? InvertPatternForExcludeInternal<p[k], i[k], empty> : InvertPattern<p[k]>;
}> : empty : empty : empty;
export {};