Skip to content

valcheckerRuntime-first validation with zero guesswork

Type-aligned initial schemas, state-aware fluent validation, tree-shakable plugins, and deterministic structured issues.

See It In Action ​

The method name identifies the step's role, while the available methods narrow as the pipeline output changes.

ts
import type { InferOutput } from 'valchecker'
import { v } from 'valchecker'

const UserSchema = v.object({
	name: v.string()
		.toTrimmed()
		.isNotEmpty(),
	email: v.string()
		.toLowercase(),
	age: [v.looseNumber()
		.isFinite()
		.isInteger()
		.isAtLeast(0)],
	role: v.union([
		v.literal('admin'),
		v.literal('user'),
		v.literal('guest'),
	]),
})

type User = InferOutput<typeof UserSchema>

const result = await UserSchema.execute(input)

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

Why Valchecker? ​

Valchecker treats runtime validation, output transformation, TypeScript inference, and bundle composition as one API design problem. Primitive initial steps mirror TypeScript types; additional runtime guarantees are explicit isXxx validations; concrete output changes are toXxx transformations. Generic check() and transform() remain available when a named step cannot express the requirement.