Dead simple Object schema validation
npx @tessl/cli install tessl/npm-yup@1.7.0Yup is a comprehensive schema validation library for JavaScript that enables runtime value parsing, transformation, and assertion. It provides an extremely expressive and fluent API for building complex validation schemas that can model interdependent validations and value transformations with full TypeScript support and static type inference.
npm install yupimport * as yup from "yup";
import { string, number, boolean, bool, date, object, array, tuple, mixed, ValidationError, ref, lazy } from "yup";
import type { InferType, Schema, ObjectSchema, ArraySchema } from "yup";For CommonJS:
const yup = require("yup");
const { string, number, boolean, bool, date, object, array, tuple, mixed, ValidationError, ref, lazy } = require("yup");import { object, string, number, InferType } from "yup";
// Define a schema
const userSchema = object({
name: string().required(),
email: string().email().required(),
age: number().positive().integer().min(18),
website: string().url().optional(),
});
// Infer TypeScript type
type User = InferType<typeof userSchema>;
// Validate data
try {
const user = await userSchema.validate({
name: "John Doe",
email: "john@example.com",
age: 25,
website: "https://johndoe.com"
});
console.log(user); // validated and potentially transformed data
} catch (error) {
console.error(error.errors); // validation error messages
}
// Synchronous validation
try {
const user = userSchema.validateSync(userData);
} catch (error) {
console.error(error.message);
}Yup is built around several key architectural components:
Schema class with specialized subclasses for different data typesInferType utility for static type extractionCore functions for creating typed validation schemas for different data types.
function mixed<T = any>(spec?: MixedOptions): MixedSchema<T>;
function string(): StringSchema;
function number(): NumberSchema;
function boolean(): BooleanSchema;
function date(): DateSchema;
function object<T extends ObjectShape = {}>(shape?: T): ObjectSchema<T>;
function array<T = any>(innerType?: Schema<T>): ArraySchema<T>;
function tuple<T extends readonly [...any[]]>(types: T): TupleSchema<T>;Core validation methods, custom test functions, and error handling for robust data validation.
// Core validation methods (available on all schemas)
validate(value: any, options?: ValidateOptions): Promise<T>;
validateSync(value: any, options?: ValidateOptions): T;
isValid(value: any, options?: ValidateOptions): Promise<boolean>;
cast(value: any, options?: CastOptions): T;
// Custom validation
test(name: string, message: string, testFn: TestFunction): Schema;
test(options: TestConfig): Schema;Helper functions for schema manipulation, references, lazy evaluation, and localization.
function ref(path: string, options?: ReferenceOptions): Reference;
function lazy<T>(builder: (value: any, options: any) => Schema<T>): LazySchema<T>;
function reach(schema: Schema, path: string, value?: any, context?: any): Schema;
function addMethod(schemaType: Schema, name: string, method: Function): void;
function setLocale(localeObject: LocaleObject): void;const personSchema = object({
firstName: string().required("First name is required"),
lastName: string().required("Last name is required"),
email: string().email("Invalid email").required(),
age: number().positive().integer().min(13, "Must be at least 13"),
});const numbersSchema = array(number().positive()).min(1).max(10);
const usersSchema = array(personSchema).required();const schema = object({
isBusiness: boolean(),
companyName: string().when("isBusiness", {
is: true,
then: (schema) => schema.required(),
otherwise: (schema) => schema.strip(),
}),
});const passwordSchema = object({
password: string().min(8).required(),
confirmPassword: string()
.oneOf([ref("password")], "Passwords must match")
.required(),
});type InferType<T extends Schema> = T extends Schema<infer U> ? U : never;
type AnySchema = Schema<any>;
type AnyObject = Record<string, any>;
interface ValidateOptions<TContext = {}> {
strict?: boolean;
abortEarly?: boolean;
stripUnknown?: boolean;
recursive?: boolean;
context?: TContext;
}
interface CastOptions<TContext = {}> {
strict?: boolean;
stripUnknown?: boolean;
context?: TContext;
}
class ValidationError extends Error {
name: "ValidationError";
message: string;
value: any;
path?: string;
type?: string;
errors: string[];
inner: ValidationError[];
}
// Advanced utility types for schema composition
type Maybe<T> = T | null | undefined;
type Optionals<T> = Extract<T, null | undefined>;
type Defined<T> = T extends undefined ? never : T;
type NotNull<T> = T extends null ? never : T;
type Flags = 's' | 'd' | '';
type SetFlag<Old extends Flags, F extends Flags> = Exclude<Old, ''> | F;
type UnsetFlag<Old extends Flags, F extends Flags> = Exclude<Old, F> extends never ? '' : Exclude<Old, F>;
// Object schema utility types
type ObjectShape = { [k: string]: Schema<any> | Reference };
type TypeFromShape<S extends ObjectShape, _C> = {
[K in keyof S]: S[K] extends Schema<any> ? S[K]['__outputType'] : S[K] extends Reference<infer T> ? T : unknown;
};
type DefaultFromShape<Shape extends ObjectShape> = {
[K in keyof Shape]: Shape[K] extends Schema<any> ? Shape[K]['__default'] : undefined;
};
type MakePartial<T extends object> = Partial<T> & Required<NonOptionalKeys<T>>;
// Test configuration types
interface TestContext<T = any, C = any> {
path: string;
options?: ValidateOptions<C>;
parent?: any;
schema: Schema<T, C>;
resolve(value: T): T;
createError(params?: CreateErrorOptions): ValidationError;
}
type TestFunction<T = any, C = any> = (
value: T,
context: TestContext<T, C>
) => boolean | string | Promise<boolean | string>;
interface TestConfig<T = any, C = any> {
name?: string;
message?: string;
test: TestFunction<T, C>;
params?: object;
exclusive?: boolean;
skipAbsent?: boolean;
}
interface CreateErrorOptions {
path?: string;
message?: string;
params?: object;
}