/** * Newtype presents a type level "rebranding" of an existing type. * * It's basic purpose is to create a branded type from an existing * type. This is much like using TypeScript type aliases, ie. * `type MyNumber = number`. However, Newtype will prevent the * existing type from being used where the Branded type is * specified. * * @module Newtype * @since 2.0.0 */ import "./_dnt.polyfills.js"; import type { Combinable } from "./combinable.js"; import type { Comparable } from "./comparable.js"; import type { Initializable } from "./initializable.js"; import type { Iso, Prism } from "./optic.js"; import type { Predicate } from "./predicate.js"; import type { Sortable } from "./sortable.js"; /** * These are phantom types used by Newtype to both identify and distinquish * between a Newtype and its representation value. */ declare const Brand: unique symbol; declare const Value: unique symbol; /** * Create a branded type from an existing type. The branded * type can be used anywhere the existing type can, but the * existing type cannot be used where the branded one can. * * It is important to note that while a Newtype looks like * a struct, its actual representation is that of the * inner type. * * @example * ```ts * import type { Newtype } from "./newtype.ts"; * * type Integer = Newtype<'Integer', number>; * * const int = 1 as unknown as Integer; * const num = 1; * * declare function addOne(n: Integer): number; * * addOne(int); // This is ok! * // addOne(num); // This is not * ``` * * @since 2.0.0 */ export type Newtype = { readonly [Brand]: B; readonly [Value]: A; }; /** * Extracts the inner type value from a Newtype. * * @example * ```ts * import type { Newtype, ToValue } from "./newtype.ts"; * * type Integer = Newtype<'Integer', number>; * * type InnerInteger = ToValue; // number * ``` * * @since 2.0.0 */ export type ToValue> = T[typeof Value]; /** * A type alias for Newtype that is useful when constructing * Newtype related runtime instances. * * @since 2.0.0 */ export type AnyNewtype = Newtype; /** * Retype an existing Comparable from an inner type to a Newtype. * * @example * ```ts * import { Newtype, getComparable } from "./newtype.ts"; * import * as N from "./number.ts"; * * type Integer = Newtype<'Integer', number>; * * const eqInteger = getComparable(N.ComparableNumber); * ``` * * @since 2.0.0 */ export declare function getComparable(eq: Comparable>): Comparable; /** * Retype an existing Sortable from an inner type to a Newtype. * * @example * ```ts * import { Newtype, getSortable } from "./newtype.ts"; * import * as N from "./number.ts"; * * type Integer = Newtype<'Integer', number>; * * const ordInteger = getSortable(N.SortableNumber); * ``` * * @since 2.0.0 */ export declare function getSortable(ord: Sortable>): Sortable; /** * Retype an existing Combinable from an inner type to a Newtype. * * @example * ```ts * import { Newtype, getCombinable } from "./newtype.ts"; * import * as N from "./number.ts"; * * type Integer = Newtype<'Integer', number>; * * const monoidInteger = getCombinable(N.InitializableNumberSum); * ``` * * @since 2.0.0 */ export declare function getCombinable(combinable: Combinable>): Combinable; /** * Retype an existing Initializable from an inner type to a Newtype. * * @example * ```ts * import { Newtype, getInitializable } from "./newtype.ts"; * import * as N from "./number.ts"; * * type Integer = Newtype<'Integer', number>; * * const monoidInteger = getInitializable(N.InitializableNumberSum); * ``` * * @since 2.0.0 */ export declare function getInitializable(initializable: Initializable>): Initializable; /** * If the Newtype and its underlying value are referentially transparent * (meaning they can always be swapped) then you can create an instance of Iso * for the Newtype for mapping back and forth. * * @example * ```ts * import * as N from "./newtype.ts"; * * type Real = N.Newtype<"Real", number>; * * const isoReal = N.iso(); * * const result1: Real = isoReal.view(1); // Turn number into Real * const result2: number = isoReal.review(result1); // Turn Real into number * ``` * * @since 2.0.0 */ export declare function iso(): Iso, T>; /** * If the Newtype and its underlying value are not referentially transparent * (meaning they can always be swapped) then you can create an instance of Prism * for the Newtype in order to optionally map into the Newtype given some * Predicate. * * @example * ```ts * import type { Option } from "./option.ts"; * * import * as N from "./newtype.ts"; * import * as O from "./option.ts"; * import { pipe } from "./fn.ts"; * * type Integer = N.Newtype<"Integer", number>; * * const prismInteger = N.prism(Number.isInteger); * * // Turn number into an Option * const result1: Option = prismInteger.view(1); * * // Turn an Option into a number or fall back to 0 if Option is None * const result2: number = pipe( * result1, * O.map(prismInteger.review), * O.getOrElse(() => 0) * ); * ``` * * @since 2.0.0 */ export declare function prism(predicate: Predicate>): Prism, T>; export {};