| /** | |
| * The `Brand` module adds compile-time names to ordinary TypeScript values so | |
| * structurally identical values cannot be mixed accidentally. A branded value | |
| * has the same runtime representation as its unbranded value; the extra | |
| * information lives in the type system unless you choose a validating | |
| * constructor. | |
| * | |
| * @since 2.0.0 | |
| */ | |
| import * as Arr from "./Array.ts" | |
| import * as Option from "./Option.ts" | |
| import * as Result from "./Result.ts" | |
| import type * as Schema from "./Schema.ts" | |
| import * as SchemaAST from "./SchemaAST.ts" | |
| import type * as SchemaIssue from "./SchemaIssue.ts" | |
| import type * as Types from "./Types.ts" | |
| const TypeId = "~effect/Brand" | |
| /** | |
| * A generic interface that defines a branded type. | |
| * | |
| * **When to use** | |
| * | |
| * Use to define a branded type such as `number & Brand<"Positive">` when | |
| * TypeScript should keep structurally identical values separate without | |
| * changing their runtime value. | |
| * | |
| * @see {@link Branded} for applying a brand key to a base type | |
| * @see {@link Constructor} for validating or constructing branded values | |
| * | |
| * @category models | |
| * @since 2.0.0 | |
| */ | |
| export interface Brand<in out Keys extends string> { | |
| readonly [TypeId]: { | |
| readonly [K in Keys]: Keys | |
| } | |
| } | |
| /** | |
| * A constructor for a branded type that provides validation and safe | |
| * construction methods. | |
| * | |
| * **When to use** | |
| * | |
| * Use as the shared callable interface for branded values when an API accepts | |
| * or returns a brand constructor and callers need throwing, `Option`, `Result`, | |
| * or type-guard validation forms. | |
| * | |
| * @see {@link nominal} for a constructor without runtime validation | |
| * @see {@link make} for creating a constructor from a validation predicate | |
| * @see {@link check} for creating a constructor from schema checks | |
| * @see {@link all} for combining brand constructors | |
| * | |
| * @category models | |
| * @since 2.0.0 | |
| */ | |
| export interface Constructor<in out B extends Brand<any>> { | |
| /** | |
| * Constructs a branded type from a value of type `Unbranded<B>`, throwing an | |
| * error if the provided value is not valid. | |
| */ | |
| (unbranded: Brand.Unbranded<B>): B | |
| /** | |
| * Constructs a branded type from a value of type `Unbranded<B>`, returning | |
| * `Some<B>` if the provided value is valid, `None` otherwise. | |
| */ | |
| option(unbranded: Brand.Unbranded<B>): Option.Option<B> | |
| /** | |
| * Constructs a branded type from a value of type `Unbranded<B>`, returning | |
| * `Success<B>` if the provided value is valid, `Failure<BrandError>` | |
| * otherwise. | |
| */ | |
| result(unbranded: Brand.Unbranded<B>): Result.Result<B, BrandError> | |
| /** | |
| * Attempts to refine the provided value of type `Unbranded<B>`, returning | |
| * `true` if the provided value is a valid branded type, `false` otherwise. | |
| */ | |
| is(unbranded: Brand.Unbranded<B>): unbranded is Brand.Unbranded<B> & B | |
| /** | |
| * The checks that are applied to the branded type. | |
| * | |
| * @internal | |
| */ | |
| checks?: readonly [SchemaAST.Check<Brand.Unbranded<B>>, ...Array<SchemaAST.Check<Brand.Unbranded<B>>>] | undefined | |
| } | |
| /** | |
| * Error returned when a branded type is constructed from an invalid value. | |
| * | |
| * **Details** | |
| * | |
| * The error wraps a `SchemaIssue.Issue`, exposes `message` through | |
| * `issue.toString()`, and formats as `BrandError(<message>)`. | |
| * | |
| * **Gotchas** | |
| * | |
| * `BrandError` is an error-like model with `_tag`, `name`, `message`, and | |
| * `toString`; it does not extend JavaScript `Error`. | |
| * | |
| * @category errors | |
| * @since 4.0.0 | |
| */ | |
| export class BrandError { | |
| constructor(issue: SchemaIssue.Issue) { | |
| this.issue = issue | |
| } | |
| /** | |
| * Discriminant used to identify brand construction failures. | |
| * | |
| * @since 4.0.0 | |
| */ | |
| readonly _tag = "BrandError" | |
| /** | |
| * Error name used by tools that inspect JavaScript error-like objects. | |
| * | |
| * @since 4.0.0 | |
| */ | |
| readonly name: string = "BrandError" | |
| /** | |
| * Schema issue describing why brand validation failed. | |
| * | |
| * @since 4.0.0 | |
| */ | |
| readonly issue: SchemaIssue.Issue | |
| /** | |
| * Human-readable rendering of the validation issue. | |
| * | |
| * @since 4.0.0 | |
| */ | |
| get message() { | |
| return this.issue.toString() | |
| } | |
| /** | |
| * Formats the brand error together with its validation message. | |
| * | |
| * @since 4.0.0 | |
| */ | |
| toString() { | |
| return `BrandError(${this.message})` | |
| } | |
| } | |
| /** | |
| * Namespace containing type-level helpers for working with branded types and | |
| * brand constructors. | |
| * | |
| * @since 2.0.0 | |
| */ | |
| export declare namespace Brand { | |
| /** | |
| * A utility type to extract a branded type from a `Constructor`. | |
| * | |
| * @category utility types | |
| * @since 2.0.0 | |
| */ | |
| export type FromConstructor<C> = C extends Constructor<infer B> ? B : never | |
| /** | |
| * A utility type to extract the unbranded value type from a brand. | |
| * | |
| * @category utility types | |
| * @since 2.0.0 | |
| */ | |
| export type Unbranded<B extends Brand<any>> = B extends infer U & Brands<B> ? U : B | |
| /** | |
| * A utility type to extract the keys of a branded type. | |
| * | |
| * @category utility types | |
| * @since 4.0.0 | |
| */ | |
| export type Keys<B extends Brand<any>> = keyof B[typeof TypeId] | |
| /** | |
| * A utility type to extract the brands from a branded type. | |
| * | |
| * @category utility types | |
| * @since 2.0.0 | |
| */ | |
| export type Brands<B extends Brand<any>> = Types.UnionToIntersection< | |
| { [K in Keys<B>]: K extends string ? Brand<K> : never }[Keys<B>] | |
| > | |
| /** | |
| * A utility type that checks that all brands have the same base type. | |
| * | |
| * @category utility types | |
| * @since 2.0.0 | |
| */ | |
| export type EnsureCommonBase< | |
| Brands extends readonly [Constructor<any>, ...Array<Constructor<any>>] | |
| > = { | |
| [B in keyof Brands]: Brand.Unbranded<Brand.FromConstructor<Brands[0]>> extends | |
| Brand.Unbranded<Brand.FromConstructor<Brands[B]>> | |
| ? Brand.Unbranded<Brand.FromConstructor<Brands[B]>> extends Brand.Unbranded<Brand.FromConstructor<Brands[0]>> | |
| ? Brands[B] | |
| : Brands[B] | |
| : "ERROR: All brands should have the same base type" | |
| } | |
| } | |
| /** | |
| * A type alias for creating branded types more concisely. | |
| * | |
| * @category utility types | |
| * @since 2.0.0 | |
| */ | |
| export type Branded<A, Key extends string> = A & Brand<Key> | |
| /** | |
| * Returns a `Constructor` that **does not apply any runtime checks** and just | |
| * returns the provided value. | |
| * | |
| * **When to use** | |
| * | |
| * Use to create nominal types that allow distinguishing between two values | |
| * of the same type but with different meanings. | |
| * | |
| * @see {@link make} for constructing branded values with validation. | |
| * @see {@link check} for constructing branded values from schema checks. | |
| * | |
| * @category constructors | |
| * @since 2.0.0 | |
| */ | |
| export function nominal<A extends Brand<any>>(): Constructor<A> { | |
| return Object.assign((input: Brand.Unbranded<A>) => input as A, { | |
| option: (input: Brand.Unbranded<A>) => Option.some(input as A), | |
| result: (input: Brand.Unbranded<A>) => Result.succeed(input as A), | |
| is: (_: Brand.Unbranded<A>): _ is Brand.Unbranded<A> & A => true | |
| }) | |
| } | |
| /** | |
| * Returns a `Constructor` that can construct a branded type from an unbranded | |
| * value using the provided `filter` predicate as validation of the input data. | |
| * | |
| * **When to use** | |
| * | |
| * Use when you want validation while constructing the branded type. | |
| * | |
| * @see {@link nominal} for a brand constructor that performs no validation. | |
| * | |
| * @category constructors | |
| * @since 4.0.0 | |
| */ | |
| export function make<A extends Brand<any>>( | |
| filter: (unbranded: Brand.Unbranded<A>) => Schema.FilterOutput | |
| ): Constructor<A> { | |
| return check(SchemaAST.makeFilter(filter)) | |
| } | |
| /** | |
| * Creates a branded type `Constructor` from one or more schema checks. | |
| * | |
| * **When to use** | |
| * | |
| * Use when you need a branded type constructor that performs runtime validation | |
| * via schema checks. | |
| * | |
| * **Details** | |
| * | |
| * Calling the returned constructor validates the unbranded value and throws on | |
| * failure. Use the returned `option`, `result`, or `is` methods for | |
| * non-throwing validation. | |
| * | |
| * @see {@link nominal} for a brand constructor without runtime validation | |
| * @see {@link all} for combining multiple brand constructors | |
| * @category constructors | |
| * @since 4.0.0 | |
| */ | |
| export function check<A extends Brand<any>>( | |
| ...checks: readonly [ | |
| SchemaAST.Check<Brand.Unbranded<A>>, | |
| ...Array<SchemaAST.Check<Brand.Unbranded<A>>> | |
| ] | |
| ): Constructor<A> { | |
| const result = (input: Brand.Unbranded<A>): Result.Result<A, BrandError> => { | |
| return Result.mapError(SchemaAST.runChecks(checks, input), (issue) => new BrandError(issue)) as any | |
| } | |
| return Object.assign((input: Brand.Unbranded<A>) => Result.getOrThrow(result(input)), { | |
| option: (input: Brand.Unbranded<A>) => Option.getSuccess(result(input)), | |
| result, | |
| is: (input: Brand.Unbranded<A>): input is Brand.Unbranded<A> & A => Result.isSuccess(result(input)), | |
| checks | |
| }) | |
| } | |
| /** | |
| * Combines one or more brand constructors to form a single branded type. | |
| * | |
| * **When to use** | |
| * | |
| * Use to require an input to satisfy every runtime check collected by the | |
| * provided brand constructors. | |
| * | |
| * **Details** | |
| * | |
| * If the provided constructors contain runtime checks, the combined | |
| * constructor succeeds only when all checks pass. If no runtime checks are | |
| * present, it behaves as a nominal constructor. | |
| * | |
| * @category combining | |
| * @since 2.0.0 | |
| */ | |
| export function all<Brands extends readonly [Constructor<any>, ...Array<Constructor<any>>]>( | |
| ...brands: Brand.EnsureCommonBase<Brands> | |
| ): Constructor< | |
| Types.UnionToIntersection<{ [B in keyof Brands]: Brand.FromConstructor<Brands[B]> }[number]> extends | |
| infer X extends Brand<any> ? X : Brand<any> | |
| > { | |
| const checks = brands.flatMap((brand) => brand.checks ?? []) | |
| return Arr.isArrayNonEmpty(checks) ? | |
| check(...checks) : | |
| nominal() | |
| } | |
Xet Storage Details
- Size:
- 9.64 kB
- Xet hash:
- 30746eb776cf11d92d7a533095577044e54dfd86049f0529a3ab1ee852fb51cb
·
Xet efficiently stores files, intelligently splitting them into unique chunks and accelerating uploads and downloads. More info.