Skip to content

API Overview

This reference summarizes Valchecker's public schema API. The normative compatibility and semantic definition is the Valchecker 1.0 Contract.

Import strategies

Default instance

ts
import { v } from 'valchecker'

The default instance contains every built-in step.

Custom instance with all steps

ts
import { allSteps, createValchecker } from 'valchecker'

const v = createValchecker({ steps: allSteps })

Selective imports

ts
import { createValchecker, isFinite, number } from 'valchecker'

const v = createValchecker({
	steps: [number, isFinite],
})

Naming convention

  • Initial steps use nouns: string(), number(), object(), looseBoolean().
  • Built-in validation steps use isXxx(): isInteger(), isStartingWith(), isLengthAtLeast().
  • Concrete transformation steps use toXxx(): toTrimmed(), toNumber(), toJSONValue().
  • Generic high-level steps retain check() and transform().
  • Flow-control and type-level utilities use their most direct names.

Message-bearing steps place their message and optional configuration in a trailing options object. A single required semantic operand remains positional. For example, use isAtLeast(0, { message }), isFinite({ message }), and toFiltered(predicate, { thisArg, message }).

Primitives

Every built-in step, linked to its entry on Primitives.

Initial schemas

Loose primitives

  • looseBigint() — a bigint or a ${bigint} string, normalized to bigint
  • looseBoolean() — a boolean or "true"/"false", normalized to boolean
  • looseNumber() — a number or a ${number} string, normalized to number

Template literals

  • templateLiteral() — an assembled TypeScript template-literal type, matched as the checker matches it

Numeric validation

Date validation

  • date()Date instances, rejecting an Invalid Date
  • isAfter() — strictly after a Date bound
  • isBefore() — strictly before a Date bound

Length, emptiness, and inclusion

Equality and nullish narrowing

  • isDefined() — rejects undefined and removes it from the output, preserving null
  • isEqualTo()Object.is equality with one primitive expectation, narrowing the output to it
  • isNonNull() — rejects null and removes it from the output, preserving undefined
  • isNonNullish() — rejects null and undefined and removes both from the output
  • isOneOf()Object.is equality against a non-empty tuple of primitives, narrowing to their union

JSON strings

  • json() — a string that parses as JSON, preserving the string

Each validation step enforces only the condition its name expresses, and preserves the successful value. For example isGreaterThan(0) accepts positive infinity; compose isFinite().isGreaterThan(0) when both constraints are required.

String formats

Value-preserving format validators, on String formats.

Parsed formats

  • isEmail() — pragmatic WHATWG <input type="email"> pattern
  • isEmoji() — the UTS #51 emoji sequence grammar, or Unicode's RGI set on request
  • isIp() — IPv4 or IPv6, with range-checked octets and :: compression
  • isIsoDate()YYYY-MM-DD calendar date, with impossible dates rejected
  • isIsoDateTime() — a date and time joined by T, with an optional offset
  • isIsoTime()HH:MM:SS time of day, with no time-zone
  • isJwt() — three base64url segments with a decodable JOSE header
  • isUrl() — WHATWG URL parse with a scheme allow-list

Pattern formats

  • isBase64() — standard RFC 4648 base64 with canonical padding
  • isBase64Url() — unpadded RFC 4648 §5 base64url
  • isCuid2() — CUID2 as @paralleldrive/cuid2 produces it, capped at 32 characters
  • isHex() — one or more hexadecimal digits, with no 0x prefix
  • isHostname() — RFC 1123 hostname, labels of 1–63 characters within 253
  • isMac() — EUI-48 MAC address with : or - separators
  • isNanoid() — one or more characters of the default Nano ID alphabet
  • isUlid() — 26 characters of Crockford base32
  • isUuid() — RFC 9562 / RFC 4122 UUID, versions 1–8 plus nil and max

Structures

Composite and collection schemas, on Structures.

Object schemas

  • looseObject() — declared own properties validated, unknown own properties preserved
  • object() — declared own properties validated, unknown properties omitted from the output
  • strictObject() — declared own properties validated, unknown own string and symbol keys rejected

Collections

  • array() — every element validated and transformed in index order
  • map() — Map keys and values validated and transformed, with transformed keys kept unique
  • record() — every own enumerable entry, open or exhaustively closed by the key schema's domain
  • set() — Set items validated and transformed in insertion order, with transformed items kept unique
  • tuple() — fixed-shape array with per-position schemas and one optional rest region

Composition

  • intersection() — executes every branch and composes compatible outputs
  • union() — the first successful branch's transformed output, with registration-aware shorthand
  • variant() — direct discriminator lookup that executes only the selected branch

Class and binary instances

  • blob() — a Blob, through a feature-detected global
  • file() — a File, through a feature-detected global
  • instance() — an instanceof check against a class

Collection size and membership

Media types

  • isMimeType() — a value's type string against allowed MIME types, with image/* wildcards

A one-element tuple marks an object property as optional — see Optional fields.

Transforms

Output transformations, on Transforms.

String transforms

Array transforms

Collection transforms

JSON transforms

Primitive conversions

  • toBigint() — native BigInt(value) conversion
  • toBoolean() — native Boolean(value) truthiness conversion
  • toDate()Date from epoch milliseconds or any string accepted by new Date(value)
  • toMappedBoolean() — explicit true/false value mappings for string, number, or bigint
  • toNumber() — native Number(value) conversion
  • toSafeNumber() — bigint to number, only within the safe integer range

General conversion

  • toString() — convert a value through its own toString method

Native conversion steps deliberately follow JavaScript semantics rather than adding hidden policy: string().toNumber() may produce NaN, and string().toBoolean() converts the non-empty string 'false' to true. Native exceptions from Number() and BigInt() become structured issues. Reach for explicit validation, or for a policy conversion such as toSafeNumber() or toMappedBoolean(), when a narrower contract is required.

Identity conversions are not exposed: number().toNumber(), boolean().toBoolean(), and bigint().toBigint() are unavailable through the state-aware API. A union or unknown output remains convertible when it is not already entirely the target primitive type.

Helpers and utilities

Flow control, escape hatches, and type-level utilities, on Helpers & Utilities.

Escape hatches

  • check() — generic custom validation escape hatch
  • transform() — generic custom output transformation escape hatch

Flow control

  • fallback() — recover earlier validation and operation failures; internal issues are fatal
  • use() — delegate to another schema

Type-level utilities

  • as() — compile-time assertion with no runtime validation
  • generic() — lazy or recursive schema construction

Execution mode

  • toAsync() — force the complete schema to return a native promise

Callback-driven steps may return direct or PromiseLike values according to their individual contract.

Execution result

ts
type ExecutionResult<T, Issue>
	= | { value: T }
		| { issues: [Issue, ...Issue[]] }

interface ExecutionIssue {
	code: string
	category: 'validation' | 'operation' | 'internal'
	message: string
	path: PropertyKey[]
	payload: unknown
	context?: IssueContext[]
}

interface IssueContext {
	type: string
	[key: string]: unknown
}
ts
const result = await schema.execute(input)

if (v.isSuccess(result)) {
	result.value
}
else {
	result.issues
}

Execution modes

execute() preserves synchronous and maybe-asynchronous completion:

ts
const synchronousResult = v.string()
	.execute('value')

const maybeAsyncSchema = v.string()
	.check(async value => value.length > 0)
const reachedAsyncWork = maybeAsyncSchema.execute('value')
const earlyFailure = maybeAsyncSchema.execute(42)

Append .toAsync() when every invocation must return a native promise.

Method chaining

Every step returns a new immutable schema:

ts
const normalizedName = v.string()
	.toTrimmed()
	.isNotEmpty({ message: 'Required' })
	.toNormalized()
	.toLowercase()

Detailed references