/** * The Decoder module contains tools for the course parsing of javascript * objects into well typed structures. In the event that parsing fails a Decoder * returns a DecodeError data structure which contains detailed information on * how and where parsing failed. * * @todo Revisit array, tuple, record, and struct to have a concept of ...rest * * @module Decoder * @since 2.0.0 */ import "./_dnt.polyfills.js"; import type { In, Kind, Out, Spread } from "./kind.js"; import type { AnyArray, NonEmptyArray } from "./array.js"; import type { Applicable } from "./applicable.js"; import type { Combinable } from "./combinable.js"; import type { Composable } from "./composable.js"; import type { Either } from "./either.js"; import type { Flatmappable } from "./flatmappable.js"; import type { FnEither } from "./fn_either.js"; import type { Literal, Schemable } from "./schemable.js"; import type { Mappable } from "./mappable.js"; import type { Predicate } from "./predicate.js"; import type { Premappable } from "./premappable.js"; import type { ReadonlyRecord } from "./record.js"; import type { Refinement } from "./refinement.js"; import type { Wrappable } from "./wrappable.js"; /** * The required tag denotes that a property in a struct or tuple is required. * This means that the key or index must exist on the struct or tuple. * * @since 2.0.0 */ export declare const required: "required"; /** * The optional tag denotes that a property in a struct or tuple is optional. * This means that the key or index may not exist on the struct or tuple. * * @since 2.0.0 */ export declare const optional: "optional"; /** * The Property type is a type level denotation that specifies whether a key or * index is required or optional. * * @since 2.0.0 */ export type Property = typeof required | typeof optional; /** * The Leaf type is the simplest of DecodeErrors. It indicates that some * concrete value did not match the expected value. The reason field is used to * indicate the expected value. * * @since 2.0.0 */ export type Leaf = { readonly tag: "Leaf"; readonly value: unknown; readonly reason: string; }; /** * The Wrap type is used to give context to an existing DecodeError. This can be * as simple as wrapping an array decode error to indicate that we first check * for an array before we check that the array matches a tuple definition. It * can also be used to constrain or annotate. * * @since 2.0.0 */ export type Wrap = { readonly tag: "Wrap"; readonly context: string; readonly error: DecodeError; }; /** * The Key type is used to contextualize an error that occurred at a key in a * struct. * * @since 2.0.0 */ export type Key = { readonly tag: "Key"; readonly key: string; readonly property: Property; readonly error: DecodeError; }; /** * The Index type is used to contextualize an error that occurred at an index in * an Array or Tuple. * * @since 2.0.0 */ export type Index = { readonly tag: "Index"; readonly index: number; readonly property: Property; readonly error: DecodeError; }; /** * The Union type is used to associate two or more DecoderErrors as a union of * errors. * * @since 2.0.0 */ export type Union = { readonly tag: "Union"; readonly errors: readonly [DecodeError, DecodeError, ...DecodeError[]]; }; /** * The Intersection type is used to associate two or more DecodeErrors as an * intersection of errors. * * @since 2.0.0 */ export type Intersection = { readonly tag: "Intersection"; readonly errors: readonly [DecodeError, DecodeError, ...DecodeError[]]; }; /** * The Many type is used to represent zero or more DecodeErrors without * context. It's purpose is to be used as both Empty and a target for * combineenation of DecodeErrors that are neither Union or Intersection types. * This allows us to build a Combinable over DecodeError. * * @since 2.0.0 */ export type Many = { readonly tag: "Many"; readonly errors: readonly DecodeError[]; }; /** * The DecodeError type is a discriminated union of potential contextualized * errors that are encountered while decoding. * * @since 2.0.0 */ export type DecodeError = Leaf | Wrap | Key | Index | Union | Intersection | Many; /** * A refinement that returns true when a DecodeError is a Leaf. * * @example * ```ts * import * as D from "./decoder.ts"; * * const result1 = D.isLeaf(D.leafErr(1, "expected string")); // true * const result2 = D.isLeaf(D.manyErr()); // false * ``` * * @since 2.0.0 */ export declare function isLeaf(err: DecodeError): err is Leaf; /** * A refinement that returns true when a DecodeError is a Wrap. * * @example * ```ts * import * as D from "./decoder.ts"; * * const result1 = D.isWrap(D.wrapErr( * "This is some context", * D.leafErr(1, "expected string") * )); // true * const result2 = D.isWrap(D.manyErr()); // false * ``` * * @since 2.0.0 */ export declare function isWrap(err: DecodeError): err is Wrap; /** * A refinement that returns true when a DecodeError is a Key. * * @example * ```ts * import * as D from "./decoder.ts"; * * const result1 = D.isKey(D.keyErr( * "one", * D.leafErr(1, "expected string") * )); // true * const result2 = D.isKey(D.manyErr()); // false * ``` * * @since 2.0.0 */ export declare function isKey(err: DecodeError): err is Key; /** * A refinement that returns true when a DecodeError is an Index. * * @example * ```ts * import * as D from "./decoder.ts"; * * const result1 = D.isIndex(D.indexErr( * 1, * D.leafErr(1, "expected string") * )); // true * const result2 = D.isIndex(D.manyErr()); // false * ``` * * @since 2.0.0 */ export declare function isIndex(err: DecodeError): err is Index; /** * A refinement that returns true when a DecodeError is a Union. * * @example * ```ts * import * as D from "./decoder.ts"; * * const result1 = D.isUnion(D.unionErr( * D.leafErr(1, "expected null"), * D.leafErr(1, "expected string") * )); // true * const result2 = D.isUnion(D.manyErr()); // false * ``` * * @since 2.0.0 */ export declare function isUnion(err: DecodeError): err is Union; /** * A refinement that returns true when a DecodeError is an Intersection. * * @example * ```ts * import * as D from "./decoder.ts"; * * const result1 = D.isIntersection(D.intersectionErr( * D.leafErr(1, "expected null"), * D.leafErr(1, "expected string") * )); // true * const result2 = D.isIntersection(D.manyErr()); // false * ``` * * @since 2.0.0 */ export declare function isIntersection(err: DecodeError): err is Intersection; /** * A refinement that returns true when a DecodeError is a Many. * * @example * ```ts * import * as D from "./decoder.ts"; * * const result1 = D.isMany(D.intersectionErr( * D.leafErr(1, "expected null"), * D.leafErr(1, "expected string") * )); // false * const result2 = D.isMany(D.manyErr()); // true * ``` * * @since 2.0.0 */ export declare function isMany(err: DecodeError): err is Many; /** * Construct a Lead from an unknown value and a reason for the decode error. * * @example * ```ts * import * as D from "./decoder.ts"; * * const result = D.leafErr(1, "expected string"); * ``` * * @since 2.0.0 */ export declare function leafErr(value: unknown, reason: string): DecodeError; /** * Construct a Wrap from context and an existing DecodeError. * * @example * ```ts * import * as D from "./decoder.ts"; * * const result = D.wrapErr( * "expected password", * D.leafErr(1, "expected string") * ); * ``` * * @since 2.0.0 */ export declare function wrapErr(context: string, error: DecodeError): DecodeError; /** * Construct a Key from a key and an existing DecodeError. * * @example * ```ts * import * as D from "./decoder.ts"; * * const result = D.keyErr( * "title", * D.leafErr(1, "expected string"), * D.required, * ); * ``` * * @since 2.0.0 */ export declare function keyErr(key: string, error: DecodeError, property?: Property): DecodeError; /** * Construct an Index from an index and an existing DecodeError. * * @example * ```ts * import * as D from "./decoder.ts"; * * const result = D.indexErr( * 1, * D.leafErr(1, "expected string"), * D.required, * ); * ``` * * @since 2.0.0 */ export declare function indexErr(index: number, error: DecodeError, property?: Property): DecodeError; /** * Construct a Union from two or more DecodeErrors. * * @example * ```ts * import * as D from "./decoder.ts"; * * const result = D.unionErr( * D.leafErr(1, "expected string"), * D.leafErr(1, "expected array"), * ); * ``` * * @since 2.0.0 */ export declare function unionErr(...errors: readonly [DecodeError, DecodeError, ...DecodeError[]]): DecodeError; /** * Construct an Intersection from two or more DecodeErrors. * * @example * ```ts * import * as D from "./decoder.ts"; * * const result = D.intersectionErr( * D.leafErr(1, "expected noninit string"), * D.leafErr(1, "expected string with no spaces"), * ); * ``` * * @since 2.0.0 */ export declare function intersectionErr(...errors: readonly [DecodeError, DecodeError, ...DecodeError[]]): DecodeError; /** * Construct a Many from zero or more DecodeErrors. * * @example * ```ts * import * as D from "./decoder.ts"; * * const result1 = D.manyErr( * D.leafErr(1, "expected noninit string"), * D.leafErr(1, "expected string with no spaces"), * ); * const result2 = D.manyErr(); * ``` * * @since 2.0.0 */ export declare function manyErr(...errors: readonly DecodeError[]): DecodeError; /** * Construct a catamorphism over DecodeError, mapping each case of a DecodeError * into the single type O. * * @example * ```ts * import type { DecodeError } from "./decoder.ts"; * import * as D from "./decoder.ts"; * import * as A from "./array.ts"; * * const countErrors: (err: DecodeError) => number = D.match( * () => 1, * (_, err) => countErrors(err), * (_, __, err) => countErrors(err), * (_, __, err) => countErrors(err), * A.fold((acc, err) => acc + countErrors(err), 0), * A.fold((acc, err) => acc + countErrors(err), 0), * A.fold((acc, err) => acc + countErrors(err), 0), * ); * * const result1 = countErrors(D.leafErr(1, "expected string")); // 1 * const result2 = countErrors(D.manyErr( * D.leafErr(1, "expected string"), * D.leafErr(1, "expected string"), * D.leafErr(1, "expected string"), * )); // 3 * ``` * * @since 2.0.0 */ export declare function match(Leaf: (value: unknown, reason: string) => O, Wrap: (context: string, error: DecodeError) => O, Key: (key: string, property: Property, error: DecodeError) => O, Index: (index: number, property: Property, error: DecodeError) => O, Union: (errors: readonly [DecodeError, DecodeError, ...DecodeError[]]) => O, Intersection: (errors: readonly [DecodeError, DecodeError, ...DecodeError[]]) => O, Many: (errors: readonly DecodeError[]) => O): (e: DecodeError) => O; /** * Given a DecodeError, this function will produce a printable tree of errors. * * @example * ```ts * import * as D from "./decoder.ts"; * * const result1 = D.draw(D.leafErr(1, "string")); * // "cannot decode 1, should be string" * * const result2 = D.draw(D.wrapErr( * "decoding password", * D.leafErr(1, "string"), * )); * // decoding password * // └─ cannot decode 1, should be string * ``` * * @since 2.0.0 */ export declare function draw(err: DecodeError): string; /** * Construct an init DecodeError. This is a many that contains no errors. * * @example * ```ts * import * as D from "./decoder.ts"; * * const result = D.init(); // DecodeError * ``` * * @since 2.0.0 */ export declare function init(): DecodeError; /** * Combine two DecodeErrors into one. If both DecodeErrors are Unions then they * are merged into a Union, if they are both Intersections then are merged into * an Intersection, otherwise they are wrapped in a Many. * * @example * ```ts * import * as D from "./decoder.ts"; * import { pipe } from "./fn.ts"; * * const result = pipe( * D.leafErr(1, "string"), * D.combine(D.leafErr("hello", "number")), * ); // Many[Leaf, Leaf] * ``` * * @since 2.0.0 */ export declare function combine(second: DecodeError): (first: DecodeError) => DecodeError; /** * The canonical implementation of Combinable for DecodeError. It contains * the methods combine and init. * * @since 2.0.0 */ export declare const CombinableDecodeError: Combinable; /** * The Decoded type is an alias of Either. This is the output * of a Decoder when the parsing fails. * * @since 2.0.0 */ export type Decoded = Either; /** * Specifies Decoded as a Higher Kinded Type, with covariant * parameter A corresponding to the 0th index of any substitutions. * * @since 2.0.0 */ export interface KindDecoded extends Kind { readonly kind: Decoded>; } /** * Construct a Decoded from a value A. * * @example * ```ts * import * as D from "./decoder.ts"; * * const result1 = D.success(1); // Decoder; * const result2 = D.success("Hello"); // Decoder; * ``` * * @since 2.0.0 */ export declare function success(a: A): Decoded; /** * Construct a Decoded failure. Specifically, this constructs a Leaf * DecodeError and wraps it in Left. * * @example * ```ts * import * as D from "./decoder.ts"; * * const result1 = D.failure(1, "string"); * // Represents a Decoded value that failed because a 1 was supplied * // when a string was expected. * ``` * * @since 2.0.0 */ export declare function failure(actual: unknown, error: string): Decoded; /** * Construct a Decoded from a DecodeError. This allows one to construct a * Decoded failure directly from DecodeErrors other than Leaf. * * @example * ```ts * import * as D from "./decoder.ts"; * * const result1 = D.fromDecodeError(D.wrapErr( * "decoding password", * D.leafErr(1, "string"), * )); * ``` * * @since 2.0.0 */ export declare function fromDecodeError(err: DecodeError): Decoded; /** * A combinator over Decoded that maps a DecodeError into a printable tree. * * @example * ```ts * import * as D from "./decoder.ts"; * import { pipe } from "./fn.ts"; * * const result1 = pipe( * D.failure(1, "string"), * D.unwrap, * ); // Left("cannot decode 1, should be string") * const result2 = pipe( * D.success(1), * D.unwrap * ); // Right(1) * ``` * * @since 2.0.0 */ export declare function unwrap(ta: Decoded): Either; /** * The canonical instance of Flatmappable for Decoded. It contains the methods of, ap, map, * join, and flatmap. * * @since 2.0.0 */ export declare const FlatmappableDecoded: Flatmappable; /** * The Decoder type represents a function that parses some input D into a * value A or a DecodeError. This isn't true parsing of a grammar but instead a * combination of refinement and error tracking. * * @since 2.0.0 */ export type Decoder = FnEither; /** * @since 2.0.1 */ export type TypeIn = U extends Decoder ? D : never; /** * @since 2.0.1 */ export type TypeOut = U extends Decoder ? A : never; /** * A type that matches any decoder type. * * @since 2.0.0 */ export type AnyDecoder = Decoder; /** * Specifies Decoder as a Higher Kinded Type, with covariant * parameter A corresponding to the 0th index of any substitutions and * contravariant paramter D corresponding to the 0th index of any substitutions. * * @since 2.0.0 */ export interface KindDecoder extends Kind { readonly kind: Decoder, Out>; } /** * Construct a Decoder from a Predicate and a reason for failure or a * Decoder from a Refinement and a reason for failure. While * decoding, the value A is passed to the predicate/refinement. If it returns * true then the result is wrapped in Success, otherwise the value and reason * are wrapped in Failure. * * @example * ```ts * import * as D from "./decoder.ts"; * import * as R from "./refinement.ts"; * import { pipe } from "./fn.ts"; * * const nonEmpty = D.fromPredicate( * (s: string) => s.length > 0, // Predicate * "noninit string" * ); * const string = D.fromPredicate(R.string, "string"); * const nonEmptyString = pipe( * string, * D.compose(nonEmpty), * ); * * const result1 = nonEmptyString(null); // Left(DecodeError) * const result2 = nonEmptyString(""); // Left(DecodeError) * const result3 = nonEmptyString("Hello"); // Right("Hello") * ``` * * @since 2.0.0 */ export declare function fromPredicate(guard: Refinement, expected: string): Decoder; export declare function fromPredicate(guard: Predicate, expected: string): Decoder; /** * Create a Decoder from a constant value A. * * @example * ```ts * import * as D from "./decoder.ts"; * * const one = D.wrap("one"); * * const result = one(null); // Right("one") * ``` * * @since 2.0.0 */ export declare function wrap(a: A): Decoder; /** * Given a Decoder returning a function A => I and a Decoder returning a value * A, combine them into a Decoder returning I. * * @example * ```ts * import * as D from "./decoder.ts"; * import { pipe } from "./fn.ts"; * * type Person = { name: string; age: number }; * const person = (name: string) => (age: number): Person => ({ name, age }); * * const result = pipe( * D.wrap(person), * D.apply(D.wrap("Brandon")), * D.apply(D.wrap(37)), * ); // Decoder * ``` * * @since 2.0.0 */ export declare function apply(ua: Decoder): (ufai: Decoder I>) => Decoder; /** * Provide an alternative Decoder to fallback against if the first one fails. * * @example * ```ts * import * as D from "./decoder.ts"; * import { pipe } from "./fn.ts"; * * const numOrStr = pipe( * D.string, * D.alt(D.number), * ); * * const result1 = numOrStr(0); // Right(0) * const result2 = numOrStr("Hello"); // Right("Hello") * const result3 = numOrStr(null); // Left(DecodeError) * ``` * * @since 2.0.0 */ export declare function alt(second: Decoder): (first: Decoder) => Decoder; /** * Map over the output of a Decoder. * * @example * ```ts * import * as D from "./decoder.ts"; * import { pipe } from "./fn.ts"; * * const stringLength = pipe( * D.string, * D.map(s => s.length), * ); * * const result1 = stringLength(null); // Left(DecodeError) * const result2 = stringLength(""); // Right(0) * const result3 = stringLength("Hello"); // Right(5) * ``` * * @since 2.0.0 */ export declare function map(fai: (a: A) => I): (ua: Decoder) => Decoder; /** * Chain the result of one decoder into a new decoder. * * @since 2.0.0 */ export declare function flatmap(faui: (a: A) => Decoder): (ua: Decoder) => Decoder; /** * Annotate the DecodeError output of an existing Decoder if it fails while * parsing. Internally, this uses the DecodeError Wrap constructor. * * @example * ```ts * import * as D from "./decoder.ts"; * import { pipe } from "./fn.ts"; * * const decoder = pipe( * D.literal("a", "b", "c", 1, 2, 3), * D.annotate("like the song"), * ); * * const result1 = decoder(1); // Right(1) * const result2 = D.unwrap(decoder("d")); * // Left(`like the song * // └─ cannot decode "d", should be "a", "b", "c", 1, 2, 3`) * * ``` * * @since 2.0.0 */ export declare function annotate(context: string): (decoder: Decoder) => Decoder; /** * Create a Decoder from a type D. * * @example * ```ts * import * as D from "./decoder.ts"; * * const num = D.id(); * * const result1 = num(1); // Right(1) * ``` * * @since 2.0.0 */ export declare function id(): Decoder; /** * Compose two Decoders where the input to second aligns with the output of * first. * * @example * ```ts * import * as D from "./decoder.ts"; * import * as S from "./string.ts"; * import { pipe } from "./fn.ts"; * * const prefixed = (prefix: T) => * D.fromPredicate(S.startsWith(prefix), `prefixed with "${prefix}"`); * * const eventMethod = pipe( * D.string, * D.compose(prefixed("on")), * ); * * const result1 = eventMethod(null); // Left(DecodeError) * const result2 = eventMethod("hello"); // Left(DecodeError) * const result3 = eventMethod("onClick"); // Right("onClick"); * ``` * * @since 2.0.0 */ export declare function compose(second: Decoder): (first: Decoder) => Decoder; /** * Map over the input of a Decoder contravariantly. This allows one to use an * existing decoder against a transformed input. * * @example * ```ts * import * as D from "./decoder.ts"; * import { pipe } from "./fn.ts"; * * const fromStr = pipe( * D.tuple(D.string, D.string), * D.premap((s) => [s, s] as const), * ); * * const result1 = fromStr("hello"); // Right(["hello", "hello"]) * const result2 = fromStr(null); // Left(DecodeError) * ``` * * @since 2.0.0 */ export declare function premap(fld: (l: L) => D): (ua: Decoder) => Decoder; /** * Map over the input and output of a Decoder. This is effectively a combination * of map and premap in a single operator. * * @example * ```ts * import * as D from "./decoder.ts"; * import { pipe } from "./fn.ts"; * * const fromStr = pipe( * D.tuple(D.string, D.string), * D.dimap( * (s) => [s, s], * ([s]) => [s, s.length] as const, * ), * ); * * const result1 = fromStr("hello"); // Right(["hello", 5]) * const result2 = fromStr(null); // Left(DecodeError) * ``` * * @since 2.0.0 */ export declare function dimap(fld: (l: L) => D, fai: (a: A) => I): (ua: Decoder) => Decoder; /** * Apply a refinement or predicate to the output of an existing Decoder. This is * useful for building complicated Decoders. * * @example * ```ts * import * as D from "./decoder.ts"; * import { pipe } from "./fn.ts"; * * const nonEmptyString = pipe( * D.string, * D.refine(s => s.length > 0, "noninit"), * ); * * const result1 = nonEmptyString(null); // Left(DecodeError) * const result2 = nonEmptyString(""); // Left(DecodeError) * const result3 = nonEmptyString("Hello"); // Right("Hello") * ``` * * @since 2.0.0 */ export declare function refine(refinement: Refinement, id: string): (from: Decoder) => Decoder; export declare function refine(refinement: Predicate, id: string): (from: Decoder) => Decoder; /** * Create a Decoder from a list of literal values. Literal values can be * strings, numbers, booleans, null, or undefined. This decoder will only return * Right if the value being decoded has object equality with one of the literals * supplied. * * @example * ```ts * import * as D from "./decoder.ts"; * * const firstThree = D.literal(1, 2, 3); * * const result1 = firstThree(0); // Left(DecodeError) * const result2 = firstThree(1); // Right(1) * const result3 = firstThree(2); // Right(2) * const result4 = firstThree(3); // Right(3) * const result5 = firstThree(null); // Left(DecodeError) * ``` * * @since 2.0.0 */ export declare function literal>(...literals: A): Decoder; /** * A Decoder that always returns true and casts the result to unknown. * * @example * ```ts * import * as D from "./decoder.ts"; * * const result1 = D.unknown(null); // Right(null) * const result2 = D.unknown("Brandon"); // Right("Brandon") * ``` * * @since 2.0.0 */ export declare const unknown: Decoder; /** * A Decoder that validates strings. * * @example * ```ts * import * as D from "./decoder.ts"; * * const result1 = D.string(null); // Left(DecodeError) * const result2 = D.string("Hello"); // Right("Hello") * ``` * * @since 2.0.0 */ export declare const string: Decoder; /** * A Decoder that validates numbers. * * @example * ```ts * import * as D from "./decoder.ts"; * * const result1 = D.number(null); // Left(DecodeError) * const result2 = D.number(1); // Right(1) * ``` * * @since 2.0.0 */ export declare const number: Decoder; /** * A Decoder that validates booleans. * * @example * ```ts * import * as D from "./decoder.ts"; * * const result1 = D.boolean(null); // Left(DecodeError) * const result2 = D.boolean(true); // Right(true) * ``` * * @since 2.0.0 */ export declare const boolean: Decoder; /** * A Decoder that attempts to decode a Date using new Date(value). If the * process of calling new Date throws or the getTime method on the new date * object returns NaN, then a failure is returned. If a Date can be derived from * the object then a Date object is returned. * * @example * ```ts * import * as D from "./decoder.ts"; * * const result1 = D.date(null); // Left(DecodeError) * const result2 = D.date(Date.now()); // Right(Date) * const result3 = D.date("1990"); // Right(Date) * const result4 = D.date(new Date()); // Right(Date) * ``` * * @since 2.0.0 */ export declare function date(a: unknown): Decoded; /** * A Decoder that checks that an object is both an Array and that it's length is * N. * * @example * ```ts * import * as D from "./decoder.ts"; * * const two = D.arrayN(2); * * const result1 = two(null); // Left(DecodeError) * const result2 = two([]); // Left(DecodeError) * const result3 = two(["hello"]); // Left(DecodeError) * const result4 = two(["hello", 2]); // Right(["hello", 2]) * ``` * * @since 2.0.0 */ export declare function arrayN(length: N): Decoder & { length: N; }>; /** * A Decoder combinator that will check that a value is a string and then * attempt to parse it as JSON. * * @example * ```ts * import * as D from "./decoder.ts"; * import { pipe } from "./fn.ts"; * * const person = D.struct({ * name: D.string, * age: D.number, * }); * const json = D.json(person); * * const result1 = json(null); // Left(DecodeError) * const result2 = json(""); // Left(DecodeError) * const result3 = json('{"name":"Brandon","age":37}'); * // Right({ name: "Brandon", age: 37 }) * ``` * * @since 2.0.0 */ export declare function json(decoder: Decoder): Decoder; /** * A Decoder combinator that intersects two existing decoders. The resultant * decoder ensures that an input matches both decoders. Nested intersection * combinators will combine and flatten their error trees. * * @example * ```ts * import * as D from "./decoder.ts"; * import { pipe } from "./fn.ts"; * * const person = pipe( * D.struct({ name: D.string }), * D.intersect(D.partial({ age: D.string })), * ); * * const result1 = person(null); // Left(DecodeError) * const result2 = person({ name: "Brandon" }); // Right({ name: "Brandon" }) * const result3 = person({ name: "Brandon", age: 37 }); * // Right({ name: "Brandon", age: 37 }) * const result4 = person({ age: 37 }); // Left(DecodeError) * ``` * * @since 2.0.0 */ export declare function intersect(second: Decoder): (first: Decoder) => Decoder>; /** * Provide an alternative Decoder to fallback against if the first one fails. * This is an alias of alt. * * @example * ```ts * import * as D from "./decoder.ts"; * import { pipe } from "./fn.ts"; * * const numOrStr = pipe( * D.string, * D.union(D.number), * ); * * const result1 = numOrStr(0); // Right(0) * const result2 = numOrStr("Hello"); // Right("Hello") * const result3 = numOrStr(null); // Left(DecodeError) * ``` * * @since 2.0.0 */ export declare function union(right: Decoder): (left: Decoder) => Decoder; /** * An internal literal instance over null used in the nullable combinator. * * @since 2.0.0 */ export declare const _null: Decoder; /** * A decoder combinator that modifies an existing decoder to accept null as an * input value and a successful return value. * * @example * ```ts * import * as D from "./decoder.ts"; * * const orNull = D.nullable(D.string); * * const result1 = orNull(null); // Right(null) * const result2 = orNull(2); // Left(DecodeError) * const result3 = orNull("Hello"); // Right("Hello") * ``` * * @since 2.0.0 */ export declare function nullable(second: Decoder): Decoder; /** * An internal literal instance over undefined used in the undefinable combinator. * * @since 2.0.0 */ export declare const _undefined: Decoder; /** * A decoder combinator that modifies an existing decoder to accept undefined * as an input value and a successful return value. * * @example * ```ts * import * as D from "./decoder.ts"; * * const orUndefined = D.undefinable(D.string); * * const result1 = orUndefined(undefined); // Right(null) * const result2 = orUndefined(2); // Left(DecodeError) * const result3 = orUndefined("Hello"); // Right("Hello") * ``` * * @since 2.0.0 */ export declare function undefinable(second: Decoder): Decoder; /** * A decoder against a record with string keys and values that match the items * decoder. * * @example * ```ts * import * as D from "./decoder.ts"; * * const strings = D.record(D.string); * * const result1 = strings(null); // Left(DecodeError) * const result2 = strings({}); // Right({}) * const result3 = strings([]); // Right({}) * const result4 = strings({"one": 1}); // Left(DecodeError) * const result5 = strings({ one: "one" }); // Right({ one: "one" }) * ``` * * @since 2.0.0 */ export declare function record(items: Decoder): Decoder>; /** * A decoder against an array with only values that adhere to the passed in * items decoder. * * @example * ```ts * import * as D from "./decoder.ts"; * * const strings = D.array(D.string); * * const result1 = strings(null); // Left(DecodeError) * const result2 = strings({}); // Left(DecodeError) * const result3 = strings([]); // Right([]) * const result4 = strings([1, 2, 3]); // Left(DecodeError) * const result5 = strings(["one", "two"]); // Right(["one", "two"]) * ``` * * @since 2.0.0 */ export declare function array(items: Decoder): Decoder>; /** * A decoder over a heterogenous tuple. This tuple can have different values for * each tuple element, but is constrained to a specific size and order. * * @example * ```ts * import * as D from "./decoder.ts"; * * const tuple = D.tuple(D.string, D.number); * * const result1 = tuple([]); // Left(DecodeError) * const result2 = tuple([3, "Hello"]); // Left(DecodeError) * const result3 = tuple(["Brandon", 37]); // Right(["Brandon", 37]) * ``` * * @since 2.0.0 */ export declare function tuple(...items: { [K in keyof A]: Decoder; }): Decoder; /** * A decoder over a heterogenous record type. This struct can have different * values at each key, and the resultant decoder will ensure that each key * matches its corresponding decoder. * * @example * ```ts * import * as D from "./decoder.ts"; * * const person = D.struct({ name: D.string, age: D.number }); * * const result1 = person({}); // Left(DecodeError) * const result2 = person(null); // Left(DecodeError) * const result3 = person({ name: "Brandon" }); // Left(DecodeError) * const result4 = person({ name: "Brandon", age: 37 }); * // Right({ name: "Brandon", age: 37 }) * ``` * * @since 2.0.0 */ export declare function struct(items: { [K in keyof A]: Decoder; }): Decoder; /** * A decoder over a heterogenous record type. This struct can have different * values at each key or the key can not exist or the value can be undefined, * and the resultant decoder will ensure that each key * matches its corresponding decoder. * * @example * ```ts * import * as D from "./decoder.ts"; * * const person = D.partial({ name: D.string, age: D.number }); * * const result1 = person({}); // Right({}) * const result2 = person(null); // Left(DecodeError) * const result3 = person({ name: "Brandon" }); // Right({ name: "Brandon" }) * const result4 = person({ name: "Brandon", age: 37 }); * // Right({ name: "Brandon", age: 37 }) * ``` * * @since 2.0.0 */ export declare function partial(items: { [K in keyof A]: Decoder; }): Decoder; /** * The Lazy decoder combinator allows for the creation of recursive or mutually * recursive decoding. The passed decoder thunk is memoized to keep the vm from * falling into an infinite loop. * * @example * ```ts * import type { Decoder } from "./decoder.ts"; * * import * as D from "./decoder.ts"; * import { pipe } from "./fn.ts"; * * type Person = { name: string; age: number; children: ReadonlyArray }; * const person = ( * name: string, * age: number, * children: ReadonlyArray = [] * ): Person => ({ name, age, children }); * * const decode: Decoder = D.lazy( * "Person", * () => D.struct({ name: D.string, age: D.number, children: D.array(decode) }), * ); * * const rufus = person("Rufus", 1); * const brandon = person("Brandon", 37, [rufus]); * const jackie = person("Jackie", 57, [brandon]); * * const result1 = decode(null); // Left(DecodeError) * const result2 = decode(rufus); // Right(rufus) * const result3 = decode(brandon); // Right(brandon) * const result4 = decode(jackie); // Right(jackie) * ``` * * @since 2.0.0 */ export declare function lazy(id: string, decoder: () => Decoder): Decoder; /** * Specifies Decoder as a Higher Kinded Type, with covariant * parameter A corresponding to the 0th index of any substitutions. This is a * specific Kind used to construct the Schemable Decoder. * * @since 2.0.0 */ export interface KindUnknownDecoder extends Kind { readonly kind: Decoder>; } /** * The canonical implementation of Applicable for Decoder. It contains * the methods of, ap, and map. * * @since 2.0.0 */ export declare const ApplicableDecoder: Applicable; /** * @since 2.0.0 */ export declare const ComposableDecoder: Composable; /** * The canonical implementation of Mappable for Decoder. It contains * the method map. * * @since 2.0.0 */ export declare const MappableDecoder: Mappable; /** * The canonical implementation of Flatmappable for Decoder. It contains * the methods of, ap, map, join, and flatmap. * * @since 2.0.0 */ export declare const FlatmappableDecoder: Flatmappable; /** * @since 2.0.0 */ export declare const PremappableDecoder: Premappable; /** * The canonical implementation of Schemable for Decoder. It contains * the methods unknown, string, number, boolean, literal, nullable, undefinable, * record, array, tuple, struct, partial, intersect, union, and lazy. * * @since 2.0.0 */ export declare const SchemableDecoder: Schemable; /** * @since 2.0.0 */ export declare const WrappableDecoder: Wrappable; /** * @since 2.0.0 */ export declare const tap: (fn: (value: A) => void) => (ua: Decoder) => Decoder; /** * @since 2.0.0 */ export declare const bind: (name: Exclude, faui: (a: A) => Decoder) => (ua: Decoder) => Decoder; /** * @since 2.0.0 */ export declare const bindTo: (name: N) => (ua: Decoder) => Decoder;