npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

valibot-fast-check

v0.1.1

Published

Generate fast-check arbitraries for Valibot schemas

Downloads

948

Readme

valibot-fast-check

Generate fast-check arbitraries from Valibot schemas for property-based testing.

Installation

pnpm add valibot-fast-check

Quick Start

import { vfc } from "valibot-fast-check";
import * as v from "valibot";
import fc from "fast-check";

// Define a Valibot schema
const UserSchema = v.object({
	name: v.pipe(v.string(), v.minLength(1), v.maxLength(50)),
	age: v.pipe(v.number(), v.integer(), v.minValue(0), v.maxValue(120)),
	email: v.pipe(v.string(), v.email()),
});

// Generate fast-check arbitraries
const userArbitrary = vfc().inputOf(UserSchema);

// Use in property-based tests
fc.assert(
	fc.property(userArbitrary, (user) => {
		// Your test logic here
		const result = v.safeParse(UserSchema, user);
		expect(result.success).toBe(true);
	})
);

API Reference

Core Methods

vfc().inputOf(schema)

Generates arbitraries that produce valid input values for the given schema.

const schema = v.pipe(v.string(), v.email());
const arbitrary = vfc().inputOf(schema);
// Generates valid email strings

vfc().outputOf(schema)

Generates arbitraries that produce parsed/transformed output values for schemas with transformations.

const schema = v.pipe(v.string(), v.trim(), v.minLength(1));
const arbitrary = vfc().outputOf(schema);
// Generates trimmed, non-empty strings

vfc().override(schema, arbitrary)

Override generation for specific schemas with custom arbitraries.

const customSchema = v.string();
const customArbitrary = fc.constant("fixed-value");

const generator = vfc().override(customSchema, customArbitrary);
// Will use customArbitrary when encountering customSchema

Supported Schema Types

Primitive Types

  • string - length (minLength, maxLength, length), content (startsWith, endsWith, includes, trim), formats (email, uuid, url), exact values (value, values)
  • number - range (minValue, maxValue, gtValue, ltValue), constraints (integer, finite, safeInteger, multipleOf), exact values (value, values)
  • bigint - range constraints and exact values
  • boolean - with value constraints
  • date - with range constraints and exact values
  • undefined, null, void, any, unknown
  • nan - generates Number.NaN

Composite Types

  • object - recursive object generation
  • array - with length constraints
  • tuple - fixed-length arrays with typed elements
  • map - generates Map instances
  • set - generates Set instances with size constraints

Special Types

  • optional - uses fc.option() with undefined
  • nullable - uses fc.option() with null
  • nullish - generates value, null, or undefined
  • enum / picklist - picks from enum values
  • literal - generates exact literal values
  • union - generates from union alternatives
  • function - generates callable functions
  • symbol - generates unique symbols

Performance Optimizations

This library includes several performance optimizations over naive filtering approaches:

Range Constraints

Instead of generating random numbers and filtering:

// ❌ Slow: generates any number, filters most out
fc.integer().filter((x) => x >= 10 && x <= 20);

// ✅ Fast: generates only valid range
fc.integer({ min: 10, max: 20 });

Discrete Values

Direct generation for exact values:

// Schema: v.pipe(v.number(), v.value(42))
// ✅ Generates: fc.constant(42)

// Schema: v.pipe(v.string(), v.values(["a", "b", "c"]))
// ✅ Generates: fc.constantFrom("a", "b", "c")

String Formats and Content

Built-in optimizations for string constraints:

// Format constraints
// Schema: v.pipe(v.string(), v.email())
// ✅ Generates: fc.emailAddress() with Valibot's email regex

// Schema: v.pipe(v.string(), v.uuid())
// ✅ Generates: fc.uuid()

// Schema: v.pipe(v.string(), v.url())
// ✅ Generates: fc.webUrl()

// Content constraints (when used individually)
// Schema: v.pipe(v.string(), v.startsWith("prefix"))
// ✅ Generates: fc.string().map(s => "prefix" + s)

// Schema: v.pipe(v.string(), v.endsWith("suffix"))
// ✅ Generates: fc.string().map(s => s + "suffix")

// Multiple content constraints fall back to filterBySchema

Complex Validations

For complex or custom constraints, falls back to schema validation with efficiency monitoring:

// Custom validations automatically use filterBySchema
const schema = v.pipe(
	v.number(),
	v.check((x) => isPrime(x)) // Custom validation
);

// Constraints that can't be optimized
const schema2 = v.pipe(
	v.number(),
	v.notValue(5), // Uses filterBySchema
	v.notValues([1, 2, 3]) // Uses filterBySchema
);

// Multiple string content constraints
const schema3 = v.pipe(
	v.string(),
	v.startsWith("hello"),
	v.endsWith("world"),
	v.includes("test") // Falls back to filterBySchema
);

Error Handling

The library provides detailed error messages for unsupported schemas and generation failures:

// Unsupported schema type
try {
	vfc().inputOf(unsupportedSchema);
} catch (error) {
	// VFCUnsupportedSchemaError: Unable to generate valid values for Valibot schema. CustomType schemas are not supported.
}

// Low success rate from filterBySchema
try {
	const restrictiveSchema = v.pipe(
		v.number(),
		v.check((x) => x === Math.PI) // Extremely low success rate
	);
	const samples = fc.sample(vfc().inputOf(restrictiveSchema), 10);
} catch (error) {
	// VFCGenerationError: Unable to generate valid values for the passed Valibot schema.
	// Please provide an override for the schema at path '.'.
}

Examples

Basic Property Testing

import { vfc } from "valibot-fast-check";
import * as v from "valibot";
import fc from "fast-check";

const schema = v.object({
	username: v.pipe(v.string(), v.minLength(3), v.maxLength(20)),
	password: v.pipe(v.string(), v.minLength(8)),
	age: v.pipe(v.number(), v.integer(), v.minValue(13)),
});

fc.assert(
	fc.property(vfc().inputOf(schema), (data) => {
		// Test that all generated data is valid
		const result = v.safeParse(schema, data);
		expect(result.success).toBe(true);

		// Test business logic
		expect(data.username.length).toBeGreaterThanOrEqual(3);
		expect(data.age).toBeGreaterThanOrEqual(13);
	})
);

Complex Nested Schemas

const AddressSchema = v.object({
	street: v.string(),
	city: v.string(),
	zipCode: v.pipe(v.string(), v.regex(/^\d{5}$/)),
});

const PersonSchema = v.object({
	name: v.string(),
	addresses: v.array(AddressSchema),
	primaryAddress: v.optional(AddressSchema),
});

const personArbitrary = vfc().inputOf(PersonSchema);
// Generates complex nested objects with arrays and optional fields

Using Overrides

const schema = v.object({
	id: v.string(), // We want specific ID format
	data: v.any(),
});

const customGenerator = vfc().override(
	v.string(),
	fc.uuid() // All strings will be UUIDs
);

const arbitrary = customGenerator.inputOf(schema);

Current Limitations

  • String combinations: Multiple content constraints with length requirements fall back to filterBySchema
  • Custom validations: v.check() and v.custom() always use filtering and may have low success rates
  • Unsupported constraints: v.notValue(), v.notValues() use filtering (low efficiency for large exclusion sets)
  • Date generation: May occasionally produce NaN dates due to fast-check limitations
  • Regex constraints: v.regex() not yet optimized (uses filterBySchema)

Acknowledgments

Inspired by zod-fast-check. This library brings the same concept to Valibot, leveraging Valibot's smaller bundle size.