Let’s build
with confidence.
A quick field guide to good data. Install VLD, describe your schema, and let TypeScript take it from there.
01 / Getting started
Install the package with your favorite package manager. VLD has zero third-party runtime dependencies.
$ npm install @oxog/vldDefine the shape of your data, then call safeParse. It returns a success result or structured validation issues without throwing.
import { v } from '@oxog/vld';const user = v.object({ name: v.string().min(2), email: v.string().email(), age: v.number().int().positive(),});type User = v.infer<typeof user>;const result = user.safeParse({ name: 'Alex Morgan', email: 'alex@example.com', age: 28,});if (result.success) { console.log(result.data); // Typed as User} else { console.log(result.error.issues);}02 / Schema essentials
Start with primitives. Chain constraints. Compose them into objects and collections.
v.string().min(2).max(100);v.string().email();v.number().int().positive();v.boolean();v.enum('admin', 'user', 'guest');v.array(v.string()).min(1);v.object({ name: v.string() });// Optional values, defaults, and transformationsv.string().optional();v.string().default('hello');v.string().transform(value => value.trim());v.coerce.number().parse('42'); // 42Use parse when you want validation to throw, or safeParse when you want to handle the result explicitly.
03 / One schema. One source of truth.
Derive your TypeScript types directly from your schemas. When a schema changes, its inferred type changes with it.
const profile = v.object({ username: v.string().min(3), bio: v.string().optional(),});type Profile = v.infer<typeof profile>;// { username: string; bio?: string }04 / Already using Zod?
VLD exposes the familiar z alias and compatible entry points. Change your import, then run your application’s checks against the new package.
// Beforeimport { z } from 'zod';// Afterimport { z } from '@oxog/vld';// Same familiar schemaconst user = z.object({ name: z.string().min(2), email: z.string().email(),});For the newer method-memoization implementation, use import { vV2 as v } from '@oxog/vld'. The V1 factory API remains the default.
05 / Take only what you need.
The Mini entry point exposes standalone functions for bundle-conscious applications.
import { object, string, number, optional } from '@oxog/vld/mini';const user = object({ name: string().min(2), age: optional(number().positive()),});06 / Clarity in every language.
Built-in error localization supports 27+ languages. Use a locale directly, or load it on demand to keep your initial bundle light.
import { v, setLocale } from '@oxog/vld';setLocale('tr');const result = v.string().email().safeParse('oops');// Or load translations only when you need themimport { setLocaleAsync } from '@oxog/vld/locales/lazy';await setLocaleAsync('ja');Ready for the deeper stuff?
Codecs, async refinements, plugins, result patterns, and the complete API live in the repository documentation.
Explore the complete reference