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
import { v } from 'valchecker'The default instance contains every built-in step.
Custom instance with all steps
import { allSteps, createValchecker } from 'valchecker'
const v = createValchecker({ steps: allSteps })Selective imports
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()andtransform(). - 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
any()— passthrough typed asanybigint()—typeof value === 'bigint'boolean()—typeof value === 'boolean'literal()— exact literal match withObject.isnever()— never succeedsnull()— the valuenullnumber()— every JavaScript number, includingNaNand the infinitiesstring()—typeof value === 'string'symbol()—typeof value === 'symbol'undefined()— the valueundefinedunknown()— passthrough typed asunknown
Loose primitives
looseBigint()— abigintor a${bigint}string, normalized tobigintlooseBoolean()— abooleanor"true"/"false", normalized tobooleanlooseNumber()— anumberor a${number}string, normalized tonumber
Template literals
templateLiteral()— an assembled TypeScript template-literal type, matched as the checker matches it
Numeric validation
isAtLeast()— inclusive lower bound on a number or bigintisAtMost()— inclusive upper bound on a number or bigintisFinite()— finite numbers, throughNumber.isFiniteisGreaterThan()— strict lower bound on a number or bigintisInteger()— integers, throughNumber.isIntegerisLessThan()— strict upper bound on a number or bigintisMultipleOf()— divisibility by a number or bigint divisorisNaN()—NaN, throughNumber.isNaNisSafeInteger()— safe integers, throughNumber.isSafeInteger
Date validation
date()—Dateinstances, rejecting an Invalid DateisAfter()— strictly after aDateboundisBefore()— strictly before aDatebound
Length, emptiness, and inclusion
isEmpty()— an observedlengthorsizeof zeroisEndingWith()— nativeString.prototype.endsWithisIncluding()— native string, array, or Set inclusion semanticsisLengthAtLeast()— inclusive lower bound on the observedlengthisLengthAtMost()— inclusive upper bound on the observedlengthisLengthExactly()— an exact observedlengthisMatching()— regular-expression matching with deterministic state resetisNotEmpty()— an observedlengthorsizegreater than zeroisStartingWith()— nativeString.prototype.startsWith
Equality and nullish narrowing
isDefined()— rejectsundefinedand removes it from the output, preservingnullisEqualTo()—Object.isequality with one primitive expectation, narrowing the output to itisNonNull()— rejectsnulland removes it from the output, preservingundefinedisNonNullish()— rejectsnullandundefinedand removes both from the outputisOneOf()—Object.isequality 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">patternisEmoji()— the UTS #51 emoji sequence grammar, or Unicode's RGI set on requestisIp()— IPv4 or IPv6, with range-checked octets and::compressionisIsoDate()—YYYY-MM-DDcalendar date, with impossible dates rejectedisIsoDateTime()— a date and time joined byT, with an optional offsetisIsoTime()—HH:MM:SStime of day, with no time-zoneisJwt()— three base64url segments with a decodable JOSE headerisUrl()— WHATWGURLparse with a scheme allow-list
Pattern formats
isBase64()— standard RFC 4648 base64 with canonical paddingisBase64Url()— unpadded RFC 4648 §5 base64urlisCuid2()— CUID2 as@paralleldrive/cuid2produces it, capped at 32 charactersisHex()— one or more hexadecimal digits, with no0xprefixisHostname()— RFC 1123 hostname, labels of 1–63 characters within 253isMac()— EUI-48 MAC address with:or-separatorsisNanoid()— one or more characters of the default Nano ID alphabetisUlid()— 26 characters of Crockford base32isUuid()— 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 preservedobject()— declared own properties validated, unknown properties omitted from the outputstrictObject()— declared own properties validated, unknown own string and symbol keys rejected
Collections
array()— every element validated and transformed in index ordermap()— Map keys and values validated and transformed, with transformed keys kept uniquerecord()— every own enumerable entry, open or exhaustively closed by the key schema's domainset()— Set items validated and transformed in insertion order, with transformed items kept uniquetuple()— fixed-shape array with per-position schemas and one optional rest region
Composition
intersection()— executes every branch and composes compatible outputsunion()— the first successful branch's transformed output, with registration-aware shorthandvariant()— direct discriminator lookup that executes only the selected branch
Class and binary instances
blob()— aBlob, through a feature-detected globalfile()— aFile, through a feature-detected globalinstance()— aninstanceofcheck against a class
Collection size and membership
isIncludingKey()— Map key membershipisIncludingValue()— Map value membershipisSizeAtLeast()— inclusive lower bound on a numericsizeisSizeAtMost()— inclusive upper bound on a numericsizeisSizeExactly()— an exact numericsize
Media types
isMimeType()— a value'stypestring against allowed MIME types, withimage/*wildcards
A one-element tuple marks an object property as optional — see Optional fields.
Transforms
Output transformations, on Transforms.
String transforms
toLowercase()— lowercase stringtoNormalized()— Unicode normalizationtoSplit()— split string outputtoTrimmed()— trim both endstoTrimmedEnd()— trim the endtoTrimmedStart()— trim the starttoUppercase()— uppercase string
Array transforms
toFiltered()— filtered array or Set outputtoLength()— length outputtoMapped()— mapped array or Set output with structured callback failures; Set outputs remain uniquetoSliced()— sliced outputtoSorted()— sorted array output
Collection transforms
toArray()— convert a Set to an item arraytoEntries()— Map entries as mutable[key, value]tuplestoKeys()— Map keys as an arraytoMappedKeys()— Map key callback transform whose mapped keys stay uniquetoMappedValues()— Map value callback transformtoSize()— extract asizevaluetoValues()— Map values as an array
JSON transforms
toJSONString()— stringify a supported value with JSON semanticstoJSONValue()— parse a JSON string withJSON.parse
Primitive conversions
toBigint()— nativeBigInt(value)conversiontoBoolean()— nativeBoolean(value)truthiness conversiontoDate()—Datefrom epoch milliseconds or any string accepted bynew Date(value)toMappedBoolean()— explicit true/false value mappings for string, number, or biginttoNumber()— nativeNumber(value)conversiontoSafeNumber()— bigint to number, only within the safe integer range
General conversion
toString()— convert a value through its owntoStringmethod
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 hatchtransform()— generic custom output transformation escape hatch
Flow control
fallback()— recover earlier validation and operation failures; internal issues are fataluse()— delegate to another schema
Type-level utilities
as()— compile-time assertion with no runtime validationgeneric()— 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
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
}const result = await schema.execute(input)
if (v.isSuccess(result)) {
result.value
}
else {
result.issues
}Execution modes
execute() preserves synchronous and maybe-asynchronous completion:
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:
const normalizedName = v.string()
.toTrimmed()
.isNotEmpty({ message: 'Required' })
.toNormalized()
.toLowercase()Detailed references
- Valchecker 1.0 Contract — normative behavior and compatibility
- Primitives — primitive, numeric, string, and narrowing validators
- String formats — value-preserving string-format validators
- Structures — object, array, union and intersection
- Transforms — output transformations
- Helpers & Utilities — flow control and utilities