schema.ts

Small, fast schema validation.

The strategy is valibot's: one tree-shakeable export per schema and action, schemas as plain data, and pipe for refinement. The internals differ:

  • Every schema and action is the same three-field object, kind, def, and run. There is no separate action type, so pipe is a loop over schemas, and every run call site loads from one object shape.
  • run returns the output directly and reports failure by counting it in ctx.fails. Nothing is allocated per node on the success path.
  • Output is copy-on-write: a container returns its input when nothing in it changed, so a valid value with no defaults, transforms, or keys to drop comes back as the same object. Callers must not assume a fresh copy, and a changed subtree still shares its unchanged siblings with the input.
  • Issue paths are built on unwind: a container prefixes its key onto the issues its child added, so valid input never touches a path.
  • Schemas with no options are constants (string, not string()).
  • Messages are derived from structured issues by format_issue, which is only bundled when used.
  • A union tries its options, and is runs, in probe mode: failures are counted without building issues.

Import as a namespace: import * as s from '@fuzdev/fuz_schema/schema.ts'. The design is described at more length in docs/design.md.

view source

Declarations
#

58 declarations

Action
#

schema.ts view source

Action<TInput, TOutput>

type Schema<TOutput, TInput, string, unknown>

import type {Action} from '@fuzdev/fuz_schema/schema.js';

A schema that refines or transforms an already-typed value, for use in pipe.

generics

Action<TInput, TOutput = TInput>
TInput
TOutput
default TInput

kind

type string

readonly

def

type unknown

readonly

run

type (value: any, ctx: SchemaContext): TOutput

readonly

value

type any

ctx

returns TOutput

~types?

Type-only, never set at runtime.

type { readonly input: TInput; }

readonly

AnySchema
#

schema.ts view source

AnySchema

type Schema<any, any, string, any>

import type {AnySchema} from '@fuzdev/fuz_schema/schema.js';

kind

type string

readonly

def

type any

readonly

run

type (value: any, ctx: SchemaContext): any

readonly

value

type any

ctx

returns any

~types?

Type-only, never set at runtime.

type { readonly input: any; }

readonly

array
#

schema.ts view source

<T extends AnySchema>(schema: T): Schema<ReturnType<T["run"]>[], InferInput<T>[], "array", T> import {array} from '@fuzdev/fuz_schema/schema.js';

Matches an array whose items all match schema. The output is the input itself when no item changed.

schema

type T

returns

Schema<ReturnType<T["run"]>[], InferInput<T>[], "array", T>

generics

array<T extends AnySchema>
T
constraint AnySchema

bigint
#

schema.ts view source

Schema<bigint, bigint, "bigint", undefined>

type Schema<bigint, bigint, "bigint", undefined>

import {bigint} from '@fuzdev/fuz_schema/schema.js';

boolean
#

schema.ts view source

Schema<boolean, boolean, "boolean", undefined>

type Schema<boolean, boolean, "boolean", undefined>

import {boolean} from '@fuzdev/fuz_schema/schema.js';

brand
#

schema.ts view source

<T extends AnySchema, const TName extends string>(schema: T, name: TName): Schema<Branded<ReturnType<T["run"]>, TName>, InferInput<T>, T["kind"], T["def"]> import {brand} from '@fuzdev/fuz_schema/schema.js';

Brands the output type of schema with name, see Branded. The input type is unchanged. The schema is returned as-is, so this adds nothing to a parse and is invisible to introspection: kind and def are the wrapped schema's.

schema

the schema to brand

type T

name

the brand's name, which exists only in the types and is not stored

type TName

returns

Schema<Branded, InferInput<T>, T["kind"], T["def"]>

generics

brand<T extends AnySchema, TName extends string>
T
constraint AnySchema
TName
constraint string

Brand
#

schema.ts view source

Brand<T> import type {Brand} from '@fuzdev/fuz_schema/schema.js';

The marker Branded adds: a required property, so unmarked values don't fit.

generics

Brand<T>
T

Branded
#

schema.ts view source

Branded<TValue, TName>

type TValue & Brand<TName>

import type {Branded} from '@fuzdev/fuz_schema/schema.js';

Strict nominal typing. A plain value of the base type is not assignable to the branded type, so the only way to get one is through a schema or a cast. Good for values that must have been validated.

type Uuid = Branded<string, 'Uuid'>; const a: Uuid = 'abc'; // error! const b: Uuid = 'abc' as Uuid; // ok

generics

Branded<TValue, TName>
TValue
TName

check
#

schema.ts view source

<T>(fn: (value: T) => boolean, expected?: string): Schema<T, T, "check", (value: T) => boolean> import {check} from '@fuzdev/fuz_schema/schema.js';

Fails when fn returns false.

fn

type (value: T) => boolean

expected

type string
default 'check'

returns

Schema<T, T, "check", (value: T) => boolean>

generics

check<T>
T

fail
#

schema.ts view source

(ctx: SchemaContext, kind: string, value: unknown, expected?: string): any import {fail} from '@fuzdev/fuz_schema/schema.js';

Records an issue. Returns value so a run can fail in expression position.

ctx

kind

type string

value

type unknown

expected

describes what was expected, defaulting to kind

type string
default kind

returns

any

mutates

  • ctx — increments `ctx.fails`, and pushes to `ctx.issues` outside probe mode

finite
#

schema.ts view source

Schema<number, number, "finite", undefined>

type Schema<number, number, "finite", undefined>

import {finite} from '@fuzdev/fuz_schema/schema.js';

Flatten
#

schema.ts view source

{ [K in keyof T]: T[K]; } import type {Flatten} from '@fuzdev/fuz_schema/schema.js';

generics

Flatten<T>
T

flavor
#

schema.ts view source

<T extends AnySchema, const TName extends string>(schema: T, name: TName): Schema<Flavored<ReturnType<T["run"]>, TName>, InferInput<T>, T["kind"], T["def"]> import {flavor} from '@fuzdev/fuz_schema/schema.js';

Flavors the output type of schema with name, see Flavored. The input type is unchanged. The schema is returned as-is, so this adds nothing to a parse and is invisible to introspection: kind and def are the wrapped schema's.

schema

the schema to flavor

type T

name

the flavor's name, which exists only in the types and is not stored

type TName

returns

Schema<Flavored, InferInput<T>, T["kind"], T["def"]>

generics

flavor<T extends AnySchema, TName extends string>
T
constraint AnySchema
TName
constraint string

Flavor
#

schema.ts view source

Flavor<T> import type {Flavor} from '@fuzdev/fuz_schema/schema.js';

The marker Flavored adds: an optional property, so unmarked values still fit.

generics

Flavor<T>
T

Flavored
#

schema.ts view source

Flavored<TValue, TName>

type TValue & Flavor<TName>

import type {Flavored} from '@fuzdev/fuz_schema/schema.js';

Loose nominal typing. A plain value of the base type is assignable to the flavored type, so producing one needs no cast or parse, but two different flavors of the same base type are not assignable to each other. Good for values like ids and units, where mixing them up is the bug to prevent.

type Email = Flavored<string, 'Email'>; type Address = Flavored<string, 'Address'>; const email: Email = 'a@b.c'; // ok const address: Address = email; // error!

generics

Flavored<TValue, TName>
TValue
TName

format_issue
#

schema.ts view source

(issue: SchemaIssue): string import {format_issue} from '@fuzdev/fuz_schema/schema.js';

Formats an issue as path: expected X, received Y.

issue

returns

string

Infer
#

schema.ts view source

Infer<T>

type T["run"] extends (...args: any) => infer R ? R : any

import type {Infer} from '@fuzdev/fuz_schema/schema.js';

The output type of a schema.

generics

Infer<T extends AnySchema>
T
constraint AnySchema

InferInput
#

schema.ts view source

InferInput<T>

type NonNullable<T["~types"]>["input"]

import type {InferInput} from '@fuzdev/fuz_schema/schema.js';

The input type a schema accepts.

generics

InferInput<T extends AnySchema>
T
constraint AnySchema

integer
#

schema.ts view source

Schema<number, number, "integer", undefined>

type Schema<number, number, "integer", undefined>

import {integer} from '@fuzdev/fuz_schema/schema.js';

is
#

schema.ts view source

<T extends AnySchema>(schema: T, value: unknown): value is InferInput<T> import {is} from '@fuzdev/fuz_schema/schema.js';

Checks whether value matches schema, without building issues and stopping at the first failure. Narrows to the input type because the output is discarded.

schema

type T

value

type unknown

returns

boolean

generics

is<T extends AnySchema>
T
constraint AnySchema

lazy
#

schema.ts view source

<T extends AnySchema>(get: () => T): Schema<ReturnType<T["run"]>, InferInput<T>, "lazy", () => T> import {lazy} from '@fuzdev/fuz_schema/schema.js';

Defers to the schema returned by get, for recursive schemas. get is called once, on first use.

get

type () => T

returns

Schema<ReturnType<T["run"]>, InferInput<T>, "lazy", () => T>

generics

lazy<T extends AnySchema>
T
constraint AnySchema

literal
#

schema.ts view source

<const T extends Literal>(value: T): Schema<T, T, "literal", T> import {literal} from '@fuzdev/fuz_schema/schema.js';

Matches a single value by ===.

value

type T

returns

Schema<T, T, "literal", T>

generics

literal<T extends Literal>
T
constraint Literal

Literal
#

schema.ts view source

Literal

type string | number | bigint | boolean | null | undefined

import type {Literal} from '@fuzdev/fuz_schema/schema.js';

loose_object
#

schema.ts view source

<T extends SchemaEntries>(entries: T): Schema<{ [K in keyof ({ [K in Exclude<keyof T, OptionalOutputKeys<T>>]: ReturnType<T[K]["run"]>; } & { [K in OptionalOutputKeys<...>]?: ReturnType<...> | undefined; })]: ({ [K in Exclude<...>]: ReturnType<...>; } & { [K in OptionalOutputKeys<...>]?: ReturnType<...> | undefined; })[K]; } & Record<...>, { [K in keyof ({ [K in Exclude<...>]: InferInput<...>; } & { [K in OptionalInputKeys<...>]?: InferInput<...> | undefined; })]: ({ [K in Exclude<...>]: InferInput<...>; } & { [K in OptionalInputKeys<...>]?: InferInput<...> | undefined; })[K]; } & Record<...>, "loose_object", T> import {loose_object} from '@fuzdev/fuz_schema/schema.js';

Matches an object with entries, keeping unknown keys as they are. The cheapest of the object schemas: unknown keys are never looked at, and the output is the input itself when no entry changed.

entries

type T

returns

Schema<{ [K in keyof ({ [K in Exclude<keyof T, OptionalOutputKeys<T>>]: ReturnType<T[K]["run"]>; } & { [K in OptionalOutputKeys<T>]?: ReturnType<T[K]["run"]> | undefined; })]: ({ [K in Exclude<keyof T, OptionalOutputKeys<T>>]: ReturnType<T[K]["run"]>; } & { [K in OptionalOutputKeys<T>]?: ReturnType<T[K]["run"]> | undefined; })[K]; } & Record<string, unknown>, { [K in keyof ({ [K in Exclude<keyof T, OptionalInputKeys<T>>]: InferInput<T[K]>; } & { [K in OptionalInputKeys<T>]?: InferInput<T[K]> | undefined; })]: ({ [K in Exclude<keyof T, OptionalInputKeys<T>>]: InferInput<T[K]>; } & { [K in OptionalInputKeys<T>]?: InferInput<T[K]> | undefined; })[K]; } & Record<string, unknown>, "loose_object", T>

generics

loose_object<T extends SchemaEntries>
T
constraint SchemaEntries

max_length
#

schema.ts view source

<T extends { length: number; }>(max: number): Schema<T, T, "max_length", number> import {max_length} from '@fuzdev/fuz_schema/schema.js';

max

type number

returns

Schema<T, T, "max_length", number>

generics

max_length<T extends { length: number }>
T
constraint { length: number }

max_value
#

schema.ts view source

<T extends number | bigint>(max: T): Schema<T, T, "max_value", T> import {max_value} from '@fuzdev/fuz_schema/schema.js';

max

type T

returns

Schema<T, T, "max_value", T>

generics

max_value<T extends number | bigint>
T
constraint number | bigint

message
#

schema.ts view source

<T extends AnySchema>(schema: T, message: string | ((issue: SchemaIssue) => string)): T import {message} from '@fuzdev/fuz_schema/schema.js';

Sets custom text on the issues schema itself reports, leaving those of its children alone. Works on actions too, and the innermost message wins. The result is otherwise indistinguishable from schema.

schema

type T

message

the text, or a function that builds it from the issue

type string | ((issue: SchemaIssue) => string)

returns

T

generics

message<T extends AnySchema>
T
constraint AnySchema

min_length
#

schema.ts view source

<T extends { length: number; }>(min: number): Schema<T, T, "min_length", number> import {min_length} from '@fuzdev/fuz_schema/schema.js';

min

type number

returns

Schema<T, T, "min_length", number>

generics

min_length<T extends { length: number }>
T
constraint { length: number }

min_value
#

schema.ts view source

<T extends number | bigint>(min: T): Schema<T, T, "min_value", T> import {min_value} from '@fuzdev/fuz_schema/schema.js';

min

type T

returns

Schema<T, T, "min_value", T>

generics

min_value<T extends number | bigint>
T
constraint number | bigint

nullable
#

schema.ts view source

<T extends AnySchema>(schema: T): Schema<ReturnType<T["run"]> | null, InferInput<T> | null, "nullable", T> import {nullable} from '@fuzdev/fuz_schema/schema.js';

Accepts null.

schema

type T

returns

Schema<ReturnType<T["run"]> | null, InferInput<T> | null, "nullable", T>

generics

nullable<T extends AnySchema>
T
constraint AnySchema

number
#

schema.ts view source

Schema<number, number, "number", undefined>

type Schema<number, number, "number", undefined>

import {number} from '@fuzdev/fuz_schema/schema.js';

Rejects NaN. Allows infinities, see finite.

object
#

schema.ts view source

<T extends SchemaEntries>(entries: T): Schema<{ [K in keyof ({ [K in Exclude<keyof T, OptionalOutputKeys<T>>]: ReturnType<T[K]["run"]>; } & { [K in OptionalOutputKeys<...>]?: ReturnType<...> | undefined; })]: ({ [K in Exclude<...>]: ReturnType<...>; } & { [K in OptionalOutputKeys<...>]?: ReturnType<...> | undefined; })[K]; }, { [K in keyof ({ [K in Exclude<...>]: InferInput<...>; } & { [K in OptionalInputKeys<...>]?: InferInput<...> | undefined; })]: ({ [K in Exclude<...>]: InferInput<...>; } & { [K in OptionalInputKeys<...>]?: InferInput<...> | undefined; })[K]; }, "object", T> import {object} from '@fuzdev/fuz_schema/schema.js';

Matches an object with entries, failing on unknown keys. The output is the input itself when no entry changed.

entries

type T

returns

Schema<{ [K in keyof ({ [K in Exclude<keyof T, OptionalOutputKeys<T>>]: ReturnType<T[K]["run"]>; } & { [K in OptionalOutputKeys<T>]?: ReturnType<T[K]["run"]> | undefined; })]: ({ [K in Exclude<keyof T, OptionalOutputKeys<T>>]: ReturnType<T[K]["run"]>; } & { [K in OptionalOutputKeys<T>]?: ReturnType<T[K]["run"]> | undefined; })[K]; }, { [K in keyof ({ [K in Exclude<keyof T, OptionalInputKeys<T>>]: InferInput<T[K]>; } & { [K in OptionalInputKeys<T>]?: InferInput<T[K]> | undefined; })]: ({ [K in Exclude<keyof T, OptionalInputKeys<T>>]: InferInput<T[K]>; } & { [K in OptionalInputKeys<T>]?: InferInput<T[K]> | undefined; })[K]; }, "object", T>

generics

object<T extends SchemaEntries>
T
constraint SchemaEntries

ObjectInput
#

schema.ts view source

{ [K in keyof ({ [K in Exclude<keyof T, OptionalInputKeys<T>>]: InferInput<T[K]>; } & { [K in OptionalInputKeys<T>]?: InferInput<...> | undefined; })]: ({ [K in Exclude<...>]: InferInput<...>; } & { [K in OptionalInputKeys<...>]?: InferInput<...> | undefined; })[K]; } import type {ObjectInput} from '@fuzdev/fuz_schema/schema.js';

generics

ObjectInput<T extends SchemaEntries>
T
constraint SchemaEntries

ObjectOutput
#

schema.ts view source

{ [K in keyof ({ [K in Exclude<keyof T, OptionalOutputKeys<T>>]: ReturnType<T[K]["run"]>; } & { [K in OptionalOutputKeys<T>]?: ReturnType<...> | undefined; })]: ({ [K in Exclude<...>]: ReturnType<...>; } & { [K in OptionalOutputKeys<...>]?: ReturnType<...> | undefined; })[K]; } import type {ObjectOutput} from '@fuzdev/fuz_schema/schema.js';

generics

ObjectOutput<T extends SchemaEntries>
T
constraint SchemaEntries

optional
#

schema.ts view source

<T extends AnySchema>(schema: T): Schema<ReturnType<T["run"]> | undefined, InferInput<T> | undefined, "optional", T> import {optional} from '@fuzdev/fuz_schema/schema.js';

Accepts undefined. As an object entry it makes the key optional.

schema

type T

returns

Schema<ReturnType<T["run"]> | undefined, InferInput<T> | undefined, "optional", T>

generics

optional<T extends AnySchema>
T
constraint AnySchema

parse
#

schema.ts view source

<T extends AnySchema>(schema: T, value: unknown): SchemaResult<ReturnType<T["run"]>> import {parse} from '@fuzdev/fuz_schema/schema.js';

Validates value, returning the output or every issue found.

schema

type T

value

type unknown

returns

SchemaResult

generics

parse<T extends AnySchema>
T
constraint AnySchema

parse_or_throw
#

schema.ts view source

<T extends AnySchema>(schema: T, value: unknown): ReturnType<T["run"]> import {parse_or_throw} from '@fuzdev/fuz_schema/schema.js';

Validates value and returns the output.

schema

type T

value

type unknown

returns

ReturnType<T["run"]>

generics

parse_or_throw<T extends AnySchema>
T
constraint AnySchema

throws

  • SchemaError - when `value` doesn't match

picklist
#

schema.ts view source

<const T extends ReadonlyArray<Literal>>(values: T): Schema<T[number], T[number], "picklist", T> import {picklist} from '@fuzdev/fuz_schema/schema.js';

Matches any of values by ===.

values

type T

returns

Schema<T[number], T[number], "picklist", T>

generics

picklist<T extends ReadonlyArray<Literal>>
T
constraint ReadonlyArray<Literal>

pipe
#

schema.ts view source

<T extends AnySchema, O1>(schema: T, a1: Action<ReturnType<T["run"]>, O1>): PipeSchema<O1, T> import {pipe} from '@fuzdev/fuz_schema/schema.js';

Runs schema then each action on its output, stopping at the first failure.

schema

type T

a1

type Action<ReturnType<T["run"]>, O1>

overloads

<T extends AnySchema, O1>(schema: T, a1: Action<ReturnType<T["run"]>, O1>): PipeSchema<O1, T>
schema T
a1 Action<ReturnType<T["run"]>, O1>
returns PipeSchema<O1, T>
<T extends AnySchema, O1, O2>(schema: T, a1: Action<ReturnType<T["run"]>, O1>, a2: Action<O1, O2>): PipeSchema<O2, T>
schema T
a1 Action<ReturnType<T["run"]>, O1>
a2 Action<O1, O2>
returns PipeSchema<O2, T>
<T extends AnySchema, O1, O2, O3>(schema: T, a1: Action<ReturnType<T["run"]>, O1>, a2: Action<O1, O2>, a3: Action<O2, O3>): PipeSchema<O3, T>
schema T
a1 Action<ReturnType<T["run"]>, O1>
a2 Action<O1, O2>
a3 Action<O2, O3>
returns PipeSchema<O3, T>
<T extends AnySchema, O1, O2, O3, O4>(schema: T, a1: Action<ReturnType<T["run"]>, O1>, a2: Action<O1, O2>, a3: Action<O2, O3>, a4: Action<O3, O4>): PipeSchema<...>
schema T
a1 Action<ReturnType<T["run"]>, O1>
a2 Action<O1, O2>
a3 Action<O2, O3>
a4 Action<O3, O4>
returns PipeSchema<O4, T>

returns

PipeSchema<O1, T>

Pipe
#

schema.ts view source

Pipe import type {Pipe} from '@fuzdev/fuz_schema/schema.js';

(call)

type <T extends AnySchema, O1>(schema: T, a1: Action<ReturnType<T["run"]>, O1>): PipeSchema<O1, T>

schema

type T

a1

type Action<ReturnType<T["run"]>, O1>
returns PipeSchema<O1, T>

PipeSchema
#

schema.ts view source

PipeSchema<TOutput, T>

type Schema<TOutput, InferInput<T>, "pipe", readonly AnySchema[]>

import type {PipeSchema} from '@fuzdev/fuz_schema/schema.js';

generics

PipeSchema<TOutput, T extends AnySchema>
TOutput
T
constraint AnySchema

kind

type "pipe"

readonly

def

type readonly AnySchema[]

readonly

run

type (value: any, ctx: SchemaContext): TOutput

readonly

value

type any

ctx

returns TOutput

~types?

Type-only, never set at runtime.

type { readonly input: InferInput<T>; }

readonly

record
#

schema.ts view source

<T extends AnySchema>(schema: T): Schema<Record<string, ReturnType<T["run"]>>, Record<string, InferInput<T>>, "record", T> import {record} from '@fuzdev/fuz_schema/schema.js';

Matches an object with string keys whose values all match schema. The output is the input itself when no value changed.

schema

type T

returns

Schema<Record<string, ReturnType<T["run"]>>, Record<string, InferInput<T>>, "record", T>

generics

record<T extends AnySchema>
T
constraint AnySchema

regex
#

schema.ts view source

(pattern: RegExp, expected?: string): Schema<string, string, "regex", RegExp> import {regex} from '@fuzdev/fuz_schema/schema.js';

pattern

must not have the g or y flag, whose lastIndex state would leak between calls

type RegExp

expected

type string
default String(pattern)

returns

Schema<string, string, "regex", RegExp>

safe_integer
#

schema.ts view source

Schema<number, number, "safe_integer", undefined>

type Schema<number, number, "safe_integer", undefined>

import {safe_integer} from '@fuzdev/fuz_schema/schema.js';

Schema
#

schema.ts view source

Schema<TOutput, TInput, TKind, TDef> import type {Schema} from '@fuzdev/fuz_schema/schema.js';

A schema or action. run returns the output for value, or reports a failure with fail and returns anything.

All schemas share this exact shape so run call sites stay monomorphic; kind-specific data goes in def.

generics

Schema<TOutput = unknown, TInput = TOutput, TKind extends string = string, TDef = unknown>
TOutput
default unknown
TInput
default TOutput
TKind
constraint string
default string
TDef
default unknown

kind

type TKind

readonly

def

type TDef

readonly

run

type (value: any, ctx: SchemaContext): TOutput

readonly

value

type any

ctx

returns TOutput

~types?

Type-only, never set at runtime.

type { readonly input: TInput; }

readonly

SchemaContext
#

schema.ts view source

SchemaContext import type {SchemaContext} from '@fuzdev/fuz_schema/schema.js';

Mutable state threaded through a single parse.

issues

One per failure, except in probe mode where it stays as it was.

type SchemaIssue[]

fails

How many failures have been reported. A container knows a child failed when this grew. Outside probe mode it equals issues.length.

type number

probe

When true only whether the value matches is wanted: failures are counted without building issues, and containers return at their first failed child. Set by union while trying options and by is.

type boolean

SchemaEntries
#

SchemaError
#

schema.ts view source

import {SchemaError} from '@fuzdev/fuz_schema/schema.js';

Thrown by parse_or_throw. The message lists every issue, one per line.

inheritance

extends: Error

issues

type SchemaIssue[]

constructor

type new (issues: SchemaIssue[]): SchemaError

issues

SchemaIssue
#

schema.ts view source

SchemaIssue import type {SchemaIssue} from '@fuzdev/fuz_schema/schema.js';

A validation failure.

kind

The kind of the schema or check that failed.

type string

expected

Describes what was expected.

type string

value

The value that failed.

type unknown

path

Keys from the root value to value, outermost first.

type PropertyKey[]

message

Custom text set by message, used by format_issue in place of the default.

type string | undefined

SchemaResult
#

schema.ts view source

SchemaResult<T>

type { ok: true; value: T; } | { ok: false; issues: SchemaIssue[]; }

import type {SchemaResult} from '@fuzdev/fuz_schema/schema.js';

generics

SchemaResult<T>
T

string
#

schema.ts view source

Schema<string, string, "string", undefined>

type Schema<string, string, "string", undefined>

import {string} from '@fuzdev/fuz_schema/schema.js';

strip_object
#

schema.ts view source

<T extends SchemaEntries>(entries: T): Schema<{ [K in keyof ({ [K in Exclude<keyof T, OptionalOutputKeys<T>>]: ReturnType<T[K]["run"]>; } & { [K in OptionalOutputKeys<...>]?: ReturnType<...> | undefined; })]: ({ [K in Exclude<...>]: ReturnType<...>; } & { [K in OptionalOutputKeys<...>]?: ReturnType<...> | undefined; })[K]; }, { [K in keyof ({ [K in Exclude<...>]: InferInput<...>; } & { [K in OptionalInputKeys<...>]?: InferInput<...> | undefined; })]: ({ [K in Exclude<...>]: InferInput<...>; } & { [K in OptionalInputKeys<...>]?: InferInput<...> | undefined; })[K]; }, "strip_object", T> import {strip_object} from '@fuzdev/fuz_schema/schema.js';

Matches an object with entries, dropping unknown keys from the output. Dropping means copying, so this costs more than object or loose_object whenever there is a key to drop. The output is the input itself when no entry changed and there was nothing to drop.

entries

type T

returns

Schema<{ [K in keyof ({ [K in Exclude<keyof T, OptionalOutputKeys<T>>]: ReturnType<T[K]["run"]>; } & { [K in OptionalOutputKeys<T>]?: ReturnType<T[K]["run"]> | undefined; })]: ({ [K in Exclude<keyof T, OptionalOutputKeys<T>>]: ReturnType<T[K]["run"]>; } & { [K in OptionalOutputKeys<T>]?: ReturnType<T[K]["run"]> | undefined; })[K]; }, { [K in keyof ({ [K in Exclude<keyof T, OptionalInputKeys<T>>]: InferInput<T[K]>; } & { [K in OptionalInputKeys<T>]?: InferInput<T[K]> | undefined; })]: ({ [K in Exclude<keyof T, OptionalInputKeys<T>>]: InferInput<T[K]>; } & { [K in OptionalInputKeys<T>]?: InferInput<T[K]> | undefined; })[K]; }, "strip_object", T>

generics

strip_object<T extends SchemaEntries>
T
constraint SchemaEntries

to_type_name
#

schema.ts view source

(value: unknown): string import {to_type_name} from '@fuzdev/fuz_schema/schema.js';

Names the type of value for messages, splitting null and array out of object.

value

type unknown

returns

string

transform
#

schema.ts view source

<T, O>(fn: (value: T) => O): Schema<O, T, "transform", (value: T) => O> import {transform} from '@fuzdev/fuz_schema/schema.js';

Replaces the value with the result of fn.

fn

type (value: T) => O

returns

Schema<O, T, "transform", (value: T) => O>

generics

transform<T, O>
T
O

union
#

schema.ts view source

<const T extends ReadonlyArray<AnySchema>>(options: T): Schema<ReturnType<T[number]["run"]>, InferInput<T[number]>, "union", T> import {union} from '@fuzdev/fuz_schema/schema.js';

Matches the first of options that accepts the value. On failure reports one issue, not the options' own.

options

type T

returns

Schema<ReturnType<T[number]["run"]>, InferInput<T[number]>, "union", T>

generics

union<T extends ReadonlyArray<AnySchema>>
T
constraint ReadonlyArray<AnySchema>

unknown
#

schema.ts view source

Schema<unknown, unknown, "unknown", undefined>

type Schema<unknown, unknown, "unknown", undefined>

import {unknown} from '@fuzdev/fuz_schema/schema.js';

Accepts anything.

variant
#

schema.ts view source

<TKey extends string, const T extends ReadonlyArray<Schema<any, any, string, SchemaEntries>>>(key: TKey, options: T): Schema<ReturnType<T[number]["run"]>, InferInput<T[number]>, "variant", { ...; }> import {variant} from '@fuzdev/fuz_schema/schema.js';

Matches the object schema in options whose key literal equals the value's, a discriminated union with constant-time dispatch.

key

the discriminator, which must be a literal entry in every option

type TKey

options

type T

returns

Schema<ReturnType<T[number]["run"]>, InferInput<T[number]>, "variant", { key: TKey; options: T; }>

generics

variant<TKey extends string, T extends ReadonlyArray<Schema<any, any, string, SchemaEntries>>>
TKey
constraint string
T
constraint ReadonlyArray<Schema<any, any, string, SchemaEntries>>

with_default
#

schema.ts view source

<T extends AnySchema>(schema: T, value: ReturnType<T["run"]>): Schema<ReturnType<T["run"]>, InferInput<T> | undefined, "default", { ...; }> import {with_default} from '@fuzdev/fuz_schema/schema.js';

Replaces undefined with value. As an object entry it makes the key optional in the input and required in the output.

schema

type T

value

returned as-is, so use only immutable defaults

type ReturnType<T["run"]>

returns

Schema<ReturnType<T["run"]>, InferInput<T> | undefined, "default", { schema: T; value: ReturnType<T["run"]>; }>

generics

with_default<T extends AnySchema>
T
constraint AnySchema

Imported by
#