veffect
Version:
powerful TypeScript validation library built on the robust foundation of Effect combining exceptional type safety, high performance, and developer experience. Taking inspiration from Effect's functional principles, VEffect delivers a balanced approach tha
424 lines • 17.5 kB
TypeScript
/**
* @since 1.0.0
*/
import type * as Either from "./Either.js";
import type * as Option from "./Option.js";
import type { Pipeable } from "./Pipeable.js";
import * as Predicate from "./Predicate.js";
import type { Contravariant, Covariant, UnionToIntersection } from "./Types.js";
import type { Unify } from "./Unify.js";
/**
* @category type ids
* @since 1.0.0
*/
export declare const MatcherTypeId: unique symbol;
/**
* @category type ids
* @since 1.0.0
*/
export type MatcherTypeId = typeof MatcherTypeId;
/**
* @category model
* @since 1.0.0
*/
export type Matcher<Input, Filters, RemainingApplied, Result, Provided> = TypeMatcher<Input, Filters, RemainingApplied, Result> | ValueMatcher<Input, Filters, RemainingApplied, Result, Provided>;
/**
* @category model
* @since 1.0.0
*/
export interface TypeMatcher<in Input, out Filters, out Remaining, out Result> extends Pipeable {
readonly _tag: "TypeMatcher";
readonly [MatcherTypeId]: {
readonly _input: Contravariant<Input>;
readonly _filters: Covariant<Filters>;
readonly _remaining: Covariant<Remaining>;
readonly _result: Covariant<Result>;
};
readonly cases: ReadonlyArray<Case>;
add<I, R, RA, A>(_case: Case): TypeMatcher<I, R, RA, A>;
}
/**
* @category model
* @since 1.0.0
*/
export interface ValueMatcher<in Input, Filters, out Remaining, out Result, Provided> extends Pipeable {
readonly _tag: "ValueMatcher";
readonly [MatcherTypeId]: {
readonly _input: Contravariant<Input>;
readonly _filters: Covariant<Filters>;
readonly _result: Covariant<Result>;
};
readonly provided: Provided;
readonly value: Either.Either<Provided, Remaining>;
add<I, R, RA, A, Pr>(_case: Case): ValueMatcher<I, R, RA, A, Pr>;
}
/**
* @category model
* @since 1.0.0
*/
export type Case = When | Not;
/**
* @category model
* @since 1.0.0
*/
export interface When {
readonly _tag: "When";
guard(u: unknown): boolean;
evaluate(input: unknown): any;
}
/**
* @category model
* @since 1.0.0
*/
export interface Not {
readonly _tag: "Not";
guard(u: unknown): boolean;
evaluate(input: unknown): any;
}
/**
* @category constructors
* @since 1.0.0
*/
export declare const type: <I>() => Matcher<I, Types.Without<never>, I, never, never>;
/**
* @category constructors
* @since 1.0.0
*/
export declare const value: <const I>(i: I) => Matcher<I, Types.Without<never>, I, never, I>;
/**
* @category constructors
* @since 1.0.0
*/
export declare const valueTags: <const I, P extends {
readonly [Tag in Types.Tags<"_tag", I> & string]: (_: Extract<I, {
readonly _tag: Tag;
}>) => any;
} & {
readonly [Tag in Exclude<keyof P, Types.Tags<"_tag", I>>]: never;
}>(fields: P) => (input: I) => Unify<ReturnType<P[keyof P]>>;
/**
* @category constructors
* @since 1.0.0
*/
export declare const typeTags: <I>() => <P extends {
readonly [Tag in Types.Tags<"_tag", I> & string]: (_: Extract<I, {
readonly _tag: Tag;
}>) => any;
} & {
readonly [Tag in Exclude<keyof P, Types.Tags<"_tag", I>>]: never;
}>(fields: P) => (input: I) => Unify<ReturnType<P[keyof P]>>;
/**
* @category combinators
* @since 1.0.0
*/
export declare const when: <R, const P extends Types.PatternPrimitive<R> | Types.PatternBase<R>, Fn extends (_: Types.WhenMatch<R, P>) => unknown>(pattern: P, f: Fn) => <I, F, A, Pr>(self: Matcher<I, F, R, A, Pr>) => Matcher<I, Types.AddWithout<F, Types.PForExclude<P>>, Types.ApplyFilters<I, Types.AddWithout<F, Types.PForExclude<P>>>, A | ReturnType<Fn>, Pr>;
/**
* @category combinators
* @since 1.0.0
*/
export declare const whenOr: <R, const P extends ReadonlyArray<Types.PatternPrimitive<R> | Types.PatternBase<R>>, Fn extends (_: Types.WhenMatch<R, P[number]>) => unknown>(...args: [...patterns: P, f: Fn]) => <I, F, A, Pr>(self: Matcher<I, F, R, A, Pr>) => Matcher<I, Types.AddWithout<F, Types.PForExclude<P[number]>>, Types.ApplyFilters<I, Types.AddWithout<F, Types.PForExclude<P[number]>>>, A | ReturnType<Fn>, Pr>;
/**
* @category combinators
* @since 1.0.0
*/
export declare const whenAnd: <R, const P extends ReadonlyArray<Types.PatternPrimitive<R> | Types.PatternBase<R>>, Fn extends (_: Types.WhenMatch<R, Types.ArrayToIntersection<P>>) => unknown>(...args: [...patterns: P, f: Fn]) => <I, F, A, Pr>(self: Matcher<I, F, R, A, Pr>) => Matcher<I, Types.AddWithout<F, Types.PForExclude<Types.ArrayToIntersection<P>>>, Types.ApplyFilters<I, Types.AddWithout<F, Types.PForExclude<Types.ArrayToIntersection<P>>>>, A | ReturnType<Fn>, Pr>;
/**
* @category combinators
* @since 1.0.0
*/
export declare const discriminator: <D extends string>(field: D) => <R, P extends Types.Tags<D, R> & string, B>(...pattern: [
first: P,
...values: Array<P>,
f: (_: Extract<R, Record<D, P>>) => B
]) => <I, F, A, Pr>(self: Matcher<I, F, R, A, Pr>) => Matcher<I, Types.AddWithout<F, Extract<R, Record<D, P>>>, Types.ApplyFilters<I, Types.AddWithout<F, Extract<R, Record<D, P>>>>, B | A, Pr>;
/**
* @category combinators
* @since 1.0.0
*/
export declare const discriminatorStartsWith: <D extends string>(field: D) => <R, P extends string, B>(pattern: P, f: (_: Extract<R, Record<D, `${P}${string}`>>) => B) => <I, F, A, Pr>(self: Matcher<I, F, R, A, Pr>) => Matcher<I, Types.AddWithout<F, Extract<R, Record<D, `${P}${string}`>>>, Types.ApplyFilters<I, Types.AddWithout<F, Extract<R, Record<D, `${P}${string}`>>>>, B | A, Pr>;
/**
* @category combinators
* @since 1.0.0
*/
export declare const discriminators: <D extends string>(field: D) => <R, P extends {
readonly [Tag in Types.Tags<D, R> & string]?: ((_: Extract<R, Record<D, Tag>>) => any) | undefined;
} & {
readonly [Tag in Exclude<keyof P, Types.Tags<D, R>>]: never;
}>(fields: P) => <I, F, A, Pr>(self: Matcher<I, F, R, A, Pr>) => Matcher<I, Types.AddWithout<F, Extract<R, Record<D, keyof P>>>, Types.ApplyFilters<I, Types.AddWithout<F, Extract<R, Record<D, keyof P>>>>, A | ReturnType<P[keyof P] & {}>, Pr>;
/**
* @category combinators
* @since 1.0.0
*/
export declare const discriminatorsExhaustive: <D extends string>(field: D) => <R, P extends {
readonly [Tag in Types.Tags<D, R> & string]: (_: Extract<R, Record<D, Tag>>) => any;
} & {
readonly [Tag in Exclude<keyof P, Types.Tags<D, R>>]: never;
}>(fields: P) => <I, F, A, Pr>(self: Matcher<I, F, R, A, Pr>) => [Pr] extends [never] ? (u: I) => Unify<A | ReturnType<P[keyof P]>> : Unify<A | ReturnType<P[keyof P]>>;
/**
* @category combinators
* @since 1.0.0
*/
export declare const tag: <R, P extends Types.Tags<"_tag", R> & string, B>(...pattern: [
first: P,
...values: Array<P>,
f: (_: Extract<R, Record<"_tag", P>>) => B
]) => <I, F, A, Pr>(self: Matcher<I, F, R, A, Pr>) => Matcher<I, Types.AddWithout<F, Extract<R, Record<"_tag", P>>>, Types.ApplyFilters<I, Types.AddWithout<F, Extract<R, Record<"_tag", P>>>>, B | A, Pr>;
/**
* @category combinators
* @since 1.0.0
*/
export declare const tagStartsWith: <R, P extends string, B>(pattern: P, f: (_: Extract<R, Record<"_tag", `${P}${string}`>>) => B) => <I, F, A, Pr>(self: Matcher<I, F, R, A, Pr>) => Matcher<I, Types.AddWithout<F, Extract<R, Record<"_tag", `${P}${string}`>>>, Types.ApplyFilters<I, Types.AddWithout<F, Extract<R, Record<"_tag", `${P}${string}`>>>>, B | A, Pr>;
/**
* @category combinators
* @since 1.0.0
*/
export declare const tags: <R, P extends {
readonly [Tag in Types.Tags<"_tag", R> & string]?: ((_: Extract<R, Record<"_tag", Tag>>) => any) | undefined;
} & {
readonly [Tag in Exclude<keyof P, Types.Tags<"_tag", R>>]: never;
}>(fields: P) => <I, F, A, Pr>(self: Matcher<I, F, R, A, Pr>) => Matcher<I, Types.AddWithout<F, Extract<R, Record<"_tag", keyof P>>>, Types.ApplyFilters<I, Types.AddWithout<F, Extract<R, Record<"_tag", keyof P>>>>, A | ReturnType<P[keyof P] & {}>, Pr>;
/**
* @category combinators
* @since 1.0.0
*/
export declare const tagsExhaustive: <R, P extends {
readonly [Tag in Types.Tags<"_tag", R> & string]: (_: Extract<R, Record<"_tag", Tag>>) => any;
} & {
readonly [Tag in Exclude<keyof P, Types.Tags<"_tag", R>>]: never;
}>(fields: P) => <I, F, A, Pr>(self: Matcher<I, F, R, A, Pr>) => [Pr] extends [never] ? (u: I) => Unify<A | ReturnType<P[keyof P]>> : Unify<A | ReturnType<P[keyof P]>>;
/**
* @category combinators
* @since 1.0.0
*/
export declare const not: <R, const P extends Types.PatternPrimitive<R> | Types.PatternBase<R>, Fn extends (_: Types.NotMatch<R, P>) => unknown>(pattern: P, f: Fn) => <I, F, A, Pr>(self: Matcher<I, F, R, A, Pr>) => Matcher<I, Types.AddOnly<F, Types.WhenMatch<R, P>>, Types.ApplyFilters<I, Types.AddOnly<F, Types.WhenMatch<R, P>>>, A | ReturnType<Fn>, Pr>;
/**
* @category predicates
* @since 1.0.0
*/
export declare const nonEmptyString: SafeRefinement<string, never>;
/**
* @category predicates
* @since 1.0.0
*/
export declare const is: <Literals extends ReadonlyArray<string | number | bigint | boolean | null>>(...literals: Literals) => Predicate.Refinement<unknown, Literals[number]>;
/**
* @category predicates
* @since 1.0.0
*/
export declare const string: Predicate.Refinement<unknown, string>;
/**
* @category predicates
* @since 1.0.0
*/
export declare const number: Predicate.Refinement<unknown, number>;
/**
* @category predicates
* @since 1.0.0
*/
export declare const any: SafeRefinement<unknown, any>;
/**
* @category predicates
* @since 1.0.0
*/
export declare const defined: <A>(u: A) => u is A & {};
/**
* @category predicates
* @since 1.0.0
*/
export declare const boolean: Predicate.Refinement<unknown, boolean>;
declare const _undefined: Predicate.Refinement<unknown, undefined>;
export {
/**
* @category predicates
* @since 1.0.0
*/
_undefined as undefined };
declare const _null: Predicate.Refinement<unknown, null>;
export {
/**
* @category predicates
* @since 1.0.0
*/
_null as null };
/**
* @category predicates
* @since 1.0.0
*/
export declare const bigint: Predicate.Refinement<unknown, bigint>;
/**
* @category predicates
* @since 1.0.0
*/
export declare const symbol: Predicate.Refinement<unknown, symbol>;
/**
* @category predicates
* @since 1.0.0
*/
export declare const date: Predicate.Refinement<unknown, Date>;
/**
* @category predicates
* @since 1.0.0
*/
export declare const record: Predicate.Refinement<unknown, {
[x: string | symbol]: unknown;
}>;
/**
* @category predicates
* @since 1.0.0
*/
export declare const instanceOf: <A extends abstract new (...args: any) => any>(constructor: A) => SafeRefinement<InstanceType<A>, never>;
/**
* @category predicates
* @since 1.0.0
*/
export declare const instanceOfUnsafe: <A extends abstract new (...args: any) => any>(constructor: A) => SafeRefinement<InstanceType<A>, InstanceType<A>>;
/**
* @category conversions
* @since 1.0.0
*/
export declare const orElse: <RA, B>(f: (b: RA) => B) => <I, R, A, Pr>(self: Matcher<I, R, RA, A, Pr>) => [Pr] extends [never] ? (input: I) => Unify<B | A> : Unify<B | A>;
/**
* @category conversions
* @since 1.0.0
*/
export declare const orElseAbsurd: <I, R, RA, A, Pr>(self: Matcher<I, R, RA, A, Pr>) => [Pr] extends [never] ? (input: I) => Unify<A> : Unify<A>;
/**
* @category conversions
* @since 1.0.0
*/
export declare const either: <I, F, R, A, Pr>(self: Matcher<I, F, R, A, Pr>) => [Pr] extends [never] ? (input: I) => Either.Either<Unify<A>, R> : Either.Either<Unify<A>, R>;
/**
* @category conversions
* @since 1.0.0
*/
export declare const option: <I, F, R, A, Pr>(self: Matcher<I, F, R, A, Pr>) => [Pr] extends [never] ? (input: I) => Option.Option<Unify<A>> : Option.Option<Unify<A>>;
/**
* @category conversions
* @since 1.0.0
*/
export declare const exhaustive: <I, F, A, Pr>(self: Matcher<I, F, never, A, Pr>) => [Pr] extends [never] ? (u: I) => Unify<A> : Unify<A>;
/**
* @since 1.0.0
* @category type ids
*/
export declare const SafeRefinementId: unique symbol;
/**
* @since 1.0.0
* @category type ids
*/
export type SafeRefinementId = typeof SafeRefinementId;
/**
* @category model
* @since 1.0.0
*/
export interface SafeRefinement<in A, out R = A> {
readonly [SafeRefinementId]: (a: A) => R;
}
declare const Fail: unique symbol;
type Fail = typeof Fail;
/**
* @since 1.0.0
*/
export declare namespace Types {
/**
* @since 1.0.0
*/
type WhenMatch<R, P> = [
0
] extends [1 & R] ? PForMatch<P> : P extends SafeRefinement<infer SP, never> ? SP : P extends Predicate.Refinement<infer _R, infer RP> ? [Extract<R, RP>] extends [infer X] ? [X] extends [never] ? RP : X : never : P extends PredicateA<infer PP> ? PP : ExtractMatch<R, PForMatch<P>>;
/**
* @since 1.0.0
*/
type NotMatch<R, P> = Exclude<R, ExtractMatch<R, PForExclude<P>>>;
/**
* @since 1.0.0
*/
type PForMatch<P> = [SafeRefinementP<ResolvePred<P>>] extends [infer X] ? X : never;
/**
* @since 1.0.0
*/
type PForExclude<P> = [SafeRefinementR<ToSafeRefinement<P>>] extends [infer X] ? X : never;
type PredicateA<A> = Predicate.Predicate<A> | Predicate.Refinement<A, A>;
type SafeRefinementP<A> = A extends never ? never : A extends SafeRefinement<infer S, infer _> ? S : A extends Function ? A : A extends Record<string, any> ? {
[K in keyof A]: SafeRefinementP<A[K]>;
} : A;
type SafeRefinementR<A> = A extends never ? never : A extends SafeRefinement<infer _, infer R> ? R : A extends Function ? A : A extends Record<string, any> ? {
[K in keyof A]: SafeRefinementR<A[K]>;
} : A;
type ResolvePred<A> = A extends never ? never : A extends Predicate.Refinement<any, infer P> ? P : A extends Predicate.Predicate<infer P> ? P : A extends SafeRefinement<any> ? A : A extends Record<string, any> ? {
[K in keyof A]: ResolvePred<A[K]>;
} : A;
type ToSafeRefinement<A> = A extends never ? never : A extends Predicate.Refinement<any, infer P> ? SafeRefinement<P, P> : A extends Predicate.Predicate<infer P> ? SafeRefinement<P, never> : A extends SafeRefinement<any> ? A : A extends Record<string, any> ? {
[K in keyof A]: ToSafeRefinement<A[K]>;
} : NonLiteralsTo<A, never>;
type NonLiteralsTo<A, T> = [A] extends [string | number | boolean | bigint] ? [string] extends [A] ? T : [number] extends [A] ? T : [boolean] extends [A] ? T : [bigint] extends [A] ? T : A : A;
/**
* @since 1.0.0
*/
type PatternBase<A> = A extends ReadonlyArray<infer _T> ? ReadonlyArray<any> | PatternPrimitive<A> : A extends Record<string, any> ? Partial<{
[K in keyof A]: PatternPrimitive<A[K] & {}> | PatternBase<A[K] & {}>;
}> : never;
/**
* @since 1.0.0
*/
type PatternPrimitive<A> = PredicateA<A> | A | SafeRefinement<any>;
/**
* @since 1.0.0
*/
interface Without<out X> {
readonly _tag: "Without";
readonly _X: X;
}
/**
* @since 1.0.0
*/
interface Only<out X> {
readonly _tag: "Only";
readonly _X: X;
}
/**
* @since 1.0.0
*/
type AddWithout<A, X> = [A] extends [Without<infer WX>] ? Without<X | WX> : [A] extends [Only<infer OX>] ? Only<Exclude<OX, X>> : never;
/**
* @since 1.0.0
*/
type AddOnly<A, X> = [A] extends [Without<infer WX>] ? [X] extends [WX] ? never : Only<X> : [A] extends [Only<infer OX>] ? [X] extends [OX] ? Only<X> : never : never;
/**
* @since 1.0.0
*/
type ApplyFilters<I, A> = A extends Only<infer X> ? X : A extends Without<infer X> ? Exclude<I, X> : never;
/**
* @since 1.0.0
*/
type Tags<D extends string, P> = P extends Record<D, infer X> ? X : never;
/**
* @since 1.0.0
*/
type ArrayToIntersection<A extends ReadonlyArray<any>> = UnionToIntersection<A[number]>;
/**
* @since 1.0.0
*/
type ExtractMatch<I, P> = [ExtractAndNarrow<I, P>] extends [infer EI] ? EI : never;
type Replace<A, B> = A extends Function ? A : A extends Record<string | number, any> ? {
[K in keyof A]: K extends keyof B ? Replace<A[K], B[K]> : A[K];
} : [B] extends [A] ? B : A;
type MaybeReplace<I, P> = [P] extends [I] ? P : [I] extends [P] ? Replace<I, P> : Fail;
type BuiltInObjects = Function | Date | RegExp | Generator | {
readonly [Symbol.toStringTag]: string;
};
type IsPlainObject<T> = T extends BuiltInObjects ? false : T extends Record<string, any> ? true : false;
type Simplify<A> = {
[K in keyof A]: A[K];
} & {};
type ExtractAndNarrow<Input, P> = unknown extends P ? Input : Input extends infer I ? Exclude<I extends ReadonlyArray<any> ? P extends ReadonlyArray<any> ? {
readonly [K in keyof I]: K extends keyof P ? ExtractAndNarrow<I[K], P[K]> : I[K];
} extends infer R ? Fail extends R[keyof R] ? never : R : never : never : IsPlainObject<I> extends true ? string extends keyof I ? I extends P ? I : never : symbol extends keyof I ? I extends P ? I : never : Simplify<{
[RK in Extract<keyof I, keyof P>]-?: ExtractAndNarrow<I[RK], P[RK]>;
} & Omit<I, keyof P>> extends infer R ? [keyof P] extends [keyof RemoveFails<R>] ? R : never : never : MaybeReplace<I, P> extends infer R ? [I] extends [R] ? I : R : never, Fail> : never;
type RemoveFails<A> = NonFailKeys<A> extends infer K ? [K] extends [keyof A] ? {
[RK in K]: A[RK];
} : {} : {};
type NonFailKeys<A> = keyof A & {} extends infer K ? K extends keyof A ? A[K] extends Fail ? never : K : never : never;
}
//# sourceMappingURL=Match.d.ts.map