/** * Creates compile-time-only wrappers around existing value types. * * A newtype lets TypeScript distinguish values with the same runtime shape, such * as two different ids that are both strings. The tag exists only in the type * system, so wrapping does not allocate a runtime object. This module includes * the base `Newtype` interface, wrapping and unwrapping helpers, optics, and * helpers for reusing carrier instances such as `Equivalence`, `Order`, * `Combiner`, and `Reducer`. * * @stability unstable * @since 4.0.0 */ import type * as Combiner from "./Combiner.ts"; import type * as Equivalence from "./Equivalence.ts"; import * as Optic from "./Optic.ts"; import type * as Order from "./Order.ts"; import type * as Reducer from "./Reducer.ts"; declare const TypeId = "~effect/Newtype"; /** * A tagged interface that wraps a carrier type under a unique key, preventing * accidental interchange of structurally identical values. * * **When to use** * * Use to define a newtype as an `interface` extending * `Newtype<"MyKey", CarrierType>` when structurally identical carrier types * should remain distinct in TypeScript. * * **Details** * * The tag is compile-time only, so no runtime wrapper is allocated. Use * {@link makeIso} to create a two-way conversion, or {@link value} to unwrap. * * **Example** (Defining a newtype) * * ```ts import.meta.vitest * import { Newtype } from "effect" * * interface UserId extends Newtype.Newtype<"UserId", number> {} * interface OrderId extends Newtype.Newtype<"OrderId", number> {} * * const userId = Newtype.makeIso().set(1) * // UserId and OrderId are not assignable to each other * // even though both wrap `number`. * // @ts-expect-error * const orderId: OrderId = userId * * Newtype.value(userId) // => 1 * ``` * * @see {@link makeIso} — create an iso to wrap and unwrap * @see {@link value} — unwrap a newtype value * * @stability unstable * @category models * @since 4.0.0 */ export interface Newtype { readonly [TypeId]: { readonly key: Key; readonly carrier: Carrier; }; } /** * Namespace containing type-level helpers for `Newtype` values, including * constraints and utilities for extracting a newtype's key and carrier type. * * **When to use** * * Use to access generic constraints and type-level utilities for `Newtype` * values. * * @stability unstable * @since 4.0.0 */ export declare namespace Newtype { /** * A type that matches any `Newtype`, useful as a generic constraint: * ``. * * **When to use** * * Use as a generic constraint when a type parameter can be any `Newtype`. * * @see {@link Newtype} — the base tagged interface * * @category utility types * @since 4.0.0 */ type Any = Newtype; /** * Extracts the key literal type from a newtype. * * **When to use** * * Use to inspect or constrain a newtype's key in generic code. * * @category utility types * @since 4.0.0 */ type Key = N extends Newtype ? Key : never; /** * Extracts the carrier (underlying) type from a newtype. * * **When to use** * * Use when you need to refer to the wrapped type in generic utilities. * * @category utility types * @since 4.0.0 */ type Carrier = N extends Newtype ? Carrier : never; } /** * Unwraps a newtype value, returning the underlying carrier value. * * **When to use** * * Use when you need the carrier value from an existing newtype without * constructing a new newtype value at the same call site. * * **Details** * * This has zero runtime cost because it is an identity cast. * * **Example** (Unwrapping a newtype) * * ```ts import.meta.vitest * import { Newtype } from "effect" * * interface Label extends Newtype.Newtype<"Label", string> {} * * const iso = Newtype.makeIso