/** * The Refinement type represents a function that takes a type and returns a * boolean. It denotes a function that narrows a type at runtime. For example * the function `(n: unknown): n is number => typeof n === "number"` is the * refinement type `Refinement`. The primary use for Refinement * is to align the runtime value with compile time types. * * @module Refinement * @since 2.0.0 */ import "./_dnt.polyfills.js"; import type { In, Kind, Out } from "./kind.js"; import type { NonEmptyArray } from "./array.js"; import type { Option } from "./option.js"; import type { Either } from "./either.js"; import type { ReadonlyRecord } from "./record.js"; import type { Literal, Schemable } from "./schemable.js"; /** * The refinement type is a function that returns a boolean indicating that a * value satisfies a type. * * @since 2.0.0 */ export type Refinement = (a: A) => a is B; /** * A type that matches any refinement type. * * @since 2.0.0 */ export type AnyRefinement = Refinement; /** * The ToIn type takes a Refinement type and returns the type of its input. * * @since 2.0.0 */ export type ToIn = T extends Refinement ? B : never; /** * The ToOut type takes a Refinement type and returns the type of its output * refinement. * * @since 2.0.0 */ export type ToOut = T extends Refinement ? A : never; /** * Specifies Refinement as a Higher Kinded Type, with covariant * parameter B corresponding to the 0th index of any substitutions and * contravariant parameter A corresponding to the 0th index of any * substitutions. * * @since 2.0.0 */ export interface KindRefinement extends Kind { readonly kind: Refinement, Out>; } /** * Specifies Refinement as a Higher Kinded Type, with covariant * parameter B corresponding to the 0th index of any substitutions. * * @since 2.0.0 */ export interface KindUnknownRefinement extends Kind { readonly kind: Refinement>; } /** * Construct a refinement from a function (a: A) => Option where None denotes * that a type does not satisfy the refinement. * * @example * ```ts * import * as R from "./refinement.ts"; * import * as O from "./option.ts"; * * const refine = R.fromOption((u: unknown) => typeof u === "number" ? O.some(u) * : O.none); * const value1: unknown = "Hello"; * const value2: unknown = 0; * * const result1 = refine(value1); // false, value1: unknown * const result2 = refine(value2); // true, value2: number * ``` * * @since 2.0.0 */ export declare function fromOption(faob: (a: A) => Option): Refinement; /** * Construct a refinement from a function (a: A) => Either where Left denotes * that a type does not satisfy the refinement. * * @example * ```ts * import * as R from "./refinement.ts"; * import * as E from "./either.ts"; * * const refine = R.fromEither((u: unknown) => typeof u === "number" ? E.right(u) * : E.left(u)); * const value1: unknown = "Hello"; * const value2: unknown = 0; * * const result1 = refine(value1); // false, value1: unknown * const result2 = refine(value2); // true, value2: number * ``` * * @since 2.0.0 */ export declare function fromEither(faob: (a: A) => Either): Refinement; /** * Compose two refinements into a new refinement that returns true if either of * the two input refinements return true. * * @example * ```ts * import * as R from "./refinement.ts"; * import { pipe } from "./fn.ts"; * * const number = (u: unknown): u is number => typeof u === "number"; * const string = (u: unknown): u is string => typeof u === "string"; * const refine = pipe(number, R.or(string)); * * const result1 = refine("Hello"); // true * const result2 = refine(null); // false * ``` * * @since 2.0.0 */ export declare function or(second: Refinement): (first: Refinement) => Refinement; /** * Compose two refinements into a new refinement that returns true if both of * the two input refinements return true. * * @example * ```ts * import type { Newtype } from "./newtype.ts"; * * import * as R from "./refinement.ts"; * import { pipe } from "./fn.ts"; * * const isBig = (s: unknown): s is "Big" => s === "Big"; * const refine = pipe(R.string, R.and(isBig)); * * const result1 = refine(null); // false * const result2 = refine("Hello"); // false * const result3 = refine("Big"); // false * ``` * * @since 2.0.0 */ export declare function and(second: Refinement): (first: Refinement) => Refinement; /** * Create a identity refinement that always returns true as at the type level a * type A is always a type A. * * @example * ```ts * import * as R from "./refinement.ts"; * * const number = R.id(); * * const result = number(1); // true.. but only numbers can be passed here. * ``` * * @since 2.0.0 */ export declare function id(): Refinement; /** * Compose two refinements, A -> B and B -> C creating a `Refinement`. * * @example * ```ts * import * as R from "./refinement.ts"; * import { pipe } from "./fn.ts"; * * type Person = { name: string }; * type Rec = Record; * * const nonnull = (u: unknown): u is Rec => u !== null && u !== undefined; * const hasKey = * (key: K) => (u: Rec): u is Record => * Object.hasOwn(u, key); * const person = (u: Record<"name", unknown>): u is Person => * typeof u.name === * "string"; * * const isPerson = pipe(nonnull, R.compose(hasKey("name")), R.compose(person)); * * const value1 = null; * const value2 = {}; * const value3 = { name: 1 }; * const value4 = { name: "Brandon" }; * * const result1 = isPerson(value1); // false * const result2 = isPerson(value2); // false * const result3 = isPerson(value3); // false * const result4 = isPerson(value4); // true, value4: Person * ``` * * @since 2.0.0 */ export declare function compose(second: Refinement): (first: Refinement) => Refinement; /** * An instance of `Refinement`. * * @example * ```ts * import * as R from "./refinement.ts"; * * const result = R.unknown(null); // true, null is unknown! all is unknown! * ``` * * @since 2.0.0 */ export declare function unknown(_: unknown): _ is unknown; /** * An instance of `Refinement`. * * @example * ```ts * import * as R from "./refinement.ts"; * * const result1 = R.string(null); // false * const result2 = R.string("Hello"); // true, a variable is now typed as string * ``` * * @since 2.0.0 */ export declare function string(a: unknown): a is string; /** * An instance of `Refinement`. * * @example * ```ts * import * as R from "./refinement.ts"; * * const result1 = R.number(null); // false * const result2 = R.number(2); // true, a variable is now typed as number * ``` * * @since 2.0.0 */ export declare function number(a: unknown): a is number; /** * An instance of `Refinement`. * * @example * ```ts * import * as R from "./refinement.ts"; * * const result1 = R.boolean(null); // false * const result2 = R.boolean(true); // true, a variable is now typed as true * ``` * * @since 2.0.0 */ export declare function boolean(a: unknown): a is boolean; /** * An instance of `Refinement>`. * * @example * ```ts * import * as R from "./refinement.ts"; * * const result1 = R.isRecord(null); // false * const result2 = R.isRecord({}); * // true, a variable is now typed as Record * ``` * * @since 2.0.0 */ export declare function isRecord(a: unknown): a is Record; /** * An instance of `Refinement>`. * * @example * ```ts * import * as R from "./refinement.ts"; * * const result1 = R.isArray(null); // false * const result2 = R.isArray([]); * // true, a variable is now typed as Array * ``` * * @since 2.0.0 */ export declare function isArray(a: unknown): a is Array; /** * Creates an instance `Refinement & { length: N }>` * where N is a number. * * @example * ```ts * import * as R from "./refinement.ts"; * * const isTwoTuple = R.isArrayN(2); * * const result1 = isTwoTuple(null); // false * const result2 = isTwoTuple([]); // false * const result3 = isTwoTuple([1, 2]); * // true, a variable is now typed as Array & { length: 2 } * ``` * * @since 2.0.0 */ export declare function isArrayN(n: N): Refinement & { length: N; }>; /** * Creates an instance of `Refinement` where P is a union of literal * values. * * @example * ```ts * import * as R from "./refinement.ts"; * * const places = R.literal(1, 2, 3); * * const result1 = places(null); // false * const result2 = places(1); // true, variable now typed as 1 | 2 | 3 * const result3 = places(2); // true, variable now typed as 1 | 2 | 3 * const result4 = places(10); // false * ``` * * @since 2.0.0 */ export declare function literal>(...literals: A): Refinement; /** * Turn a `Refinement` into `Refinement`. * * @example * ```ts * import * as R from "./refinement.ts"; * * const nullOrNum = R.nullable(R.number); * * const result1 = nullOrNum(null); // true, variable is now null | number * const result2 = nullOrNum(1); // true, variable is now null | number * const result3 = nullOrNum("hello"); // false * ``` * * @since 2.0.0 */ export declare function nullable(or: Refinement): Refinement; /** * Turn a `Refinement` into `Refinement`. * * @example * ```ts * import * as R from "./refinement.ts"; * * const test = R.undefinable(R.number); * * const result1 = test(null); // false * const result2 = test(1); // true, variable is now undefined | number * const result3 = test("hello"); // false * const result4 = test(undefined); // true, variable is now undefined | number * ``` * * @since 2.0.0 */ export declare function undefinable(or: Refinement): Refinement; /** * Turn a `Refinement` into `Refinement>`. * * @example * ```ts * import * as R from "./refinement.ts"; * * const numbers = R.record(R.number); * * const result1 = numbers(null); // false * const result2 = numbers({}); // true, {} has type ReadonlyRecord * const result3 = numbers({ hello: "world" }); // false * const result4 = numbers({ hello: 1 }); * // true, variable has type ReadonlyRecord * ``` * * @since 2.0.0 */ export declare function record(codomain: Refinement): Refinement>; /** * Turn a `Refinement` into `Refinement>`. * * @example * ```ts * import * as R from "./refinement.ts"; * * const numbers = R.array(R.number); * * const result1 = numbers(null); // false * const result2 = numbers([]); // true, [] has type ReadonlyArray * const result3 = numbers(["Hello"]); // false * const result4 = numbers([1]); * // true, variable has type ReadonlyArray * ``` * * @since 2.0.0 */ export declare function array(item: Refinement): Refinement>; /** * Create a Refinement from an array of refinements, where each index of a type * much match the originated refinement type. * * @example * ```ts * import * as R from "./refinement.ts"; * * const tuple = R.tuple(R.number, R.string); * * const result1 = tuple(null); // false * const result2 = tuple([]); // false * const result3 = tuple(["Hello", 1]); // false * const result4 = tuple([1, "Hello"]); * // true, variable has type [number, string] * const result5 = tuple([1, "Hello", "Goodbye"]); // false * ``` * * @since 2.0.0 */ export declare function tuple(...items: { [K in keyof A]: Refinement; }): Refinement; /** * Create a Refinement from a struct of refinements, where each index of a type * much match the originated refinement type, key for key. * * @example * ```ts * import * as R from "./refinement.ts"; * * const struct = R.struct({ * num: R.number, * str: R.string * }); * * const result1 = struct(null); // false * const result2 = struct({}); // false * const result3 = struct({ num: "Hello", str: 1 }); // false * const result4 = struct({ num: 1, str: "Hello" }); * // true, variable has type { num: number, str: string } * const result5 = struct([1, "Hello", "Goodbye"]); // false * ``` * * @since 2.0.0 */ export declare function struct(items: { [K in keyof A]: Refinement; }): Refinement; /** * Create a Refinement from a struct of refinements, where each index of a type * much match the originated refinement type, key for key, or not have that * property at all. This is distinct from the property being null or undefined. * * @example * ```ts * import * as R from "./refinement.ts"; * * const struct = R.partial({ * num: R.number, * str: R.string * }); * * const result1 = struct(null); // false * const result2 = struct({}); // true, * const result3 = struct({ num: "Hello", str: 1 }); // false * const result4 = struct({ num: 1, str: "Hello" }); * // true, variable has type { num?: number, str": string } * const result5 = struct({ * num: 1, * str: "Hello", * other: "Goodbye" * }); // true, variable ahs type { num?: number, str?: string } * ``` * * @since 2.0.0 */ export declare function partial(items: { [K in keyof A]: Refinement; }): Refinement; /** * Intersect is an alias of and. * * @since 2.0.0 */ export declare function intersect(gi: Refinement): (ga: Refinement) => Refinement; /** * Union is an alias of or. * * @since 2.0.0 */ export declare function union(gi: Refinement): (ga: Refinement) => Refinement; /** * Lazy is used to handle the case where a refinement is recursive. * * @example * ```ts * import type { Refinement } from "./refinement.ts"; * import * as R from "./refinement.ts"; * * type Person = { name: string; age: number; children: ReadonlyArray }; * * const person: Refinement = R.lazy("Person", () => * R.struct({ * name: R.string, * age: R.number, * children: R.array(person), * })); * * const rufus = { name: "Rufus", age: 1, children: [] }; * const brandon = { name: "Brandon", age: 37, children: [rufus] }; * * const result1 = person(null); // false * const result2 = person(rufus); // true, rufus: Person * const result3 = person(brandon); // true, brandon: Person * ``` * * @since 2.0.0 */ export declare function lazy(_: string, refinement: () => Refinement): Refinement; /** * The canonical implementation of Schemable for UnknownRefinement. 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 SchemableRefinement: Schemable;