ealush/vest

Vest ✅ Declarative validations framework

TypeScript

2,668

1,940 commits

updated Oct 12, 2026

See the code

README

Vest — form validation written like unit tests

Vest

Documentation · Async race demo · Getting started

Join Discord GitHub Stars Version Downloads Bundle size Status

Vest runs the tests for the field or step that changed and keeps the results for everything else. When async checks overlap, only the latest result can update the suite.

Vest validates what changed, remembers what already passed, and prevents stale async validation results.

The validation rules read like unit tests. The stateful runtime is what makes Vest different.

import { create, enforce, test } from 'vest';

const suite = create(data => {
  test('username', 'Username is required', () => {
    enforce(data.username).isNotBlank();
  });

  test('username', 'Username must be at least 3 characters', () => {
    enforce(data.username).longerThanOrEquals(3);
  });

  test('username', 'Username is already taken', async ({ signal }) => {
    const response = await checkUsername(data.username, { signal });
    enforce(response.available).isTruthy();
  });
});

// Run only username tests and retain previous results for every other field.
const result = suite.only('username').run(formData);

result.isPending('username');
result.hasErrors('username');

// Await the current async run when final completion matters.
await result;

Why Vest?

  • Incremental execution: Validate a field, group, or step without rerunning everything.
  • Retained validation state: A focused run updates part of the existing result instead of replacing it.
  • Race-safe async: Track pending work, cancel obsolete requests, and ignore stale completions.
  • Real workflow primitives: Model dependent fields, conditional sections, warnings, optional values, groups, and dynamic lists.
  • Client and server continuity: Run statelessly on the server and resume full validation state in the browser.
  • Framework independence: Use the same suite with React, Vue, Svelte, Angular, vanilla JavaScript, or Node.js.
  • TypeScript and schemas: Infer typed inputs and parsed outputs with Enforce schemas.
  • Standard Schema interoperability: Pass suites and Enforce rules to compatible tools while keeping run() and runStatic() as Vest's execution APIs.
  • Familiar, testable rules: Keep business validation outside UI components in suites that are easy to unit-test.

Where Vest fits

LayerResponsibilityTypical tools
Form stateValues, registration, touched state, submissionReact Hook Form, Formik
Data boundaryParse and protect a complete payloadZod, Valibot, Ajv, Enforce schemas
Validation stateDecide what runs now, retain results, coordinate async workVest

These layers are complementary. A common architecture uses a form manager for input mechanics, Vest for progressive interaction, and a schema validator for the final submitted boundary.

Where Vest works well

Vest works well for:

  • async username, email, inventory, coupon, or eligibility checks;
  • onboarding and multi-step workflows;
  • linked fields and cross-field business rules;
  • warnings that should not block submission;
  • optional and conditional sections;
  • dynamic lists of travelers, products, or addresses;
  • rules shared between browser and server;
  • SSR workflows that should not validate everything twice.

For a trivial synchronous form or a one-shot API parse, native HTML validation or a schema validator may be all you need.

Installation

npm i vest

Start here

Contributing

Contributions are welcome. See CONTRIBUTING.md.

form
forms
form-validation
hacktoberfest
javascript
react-validation
react-validation-library
svelte-validation
typescript
unit-testing
validation
validation-library
vue-validation

ealush/vest

Vest ✅ Declarative validations framework

TypeScript

2,668

1,940 commits

updated Oct 12, 2026

See the code

README

Vest — form validation written like unit tests

Vest

Documentation · Async race demo · Getting started

Join Discord GitHub Stars Version Downloads Bundle size Status

Vest runs the tests for the field or step that changed and keeps the results for everything else. When async checks overlap, only the latest result can update the suite.

Vest validates what changed, remembers what already passed, and prevents stale async validation results.

The validation rules read like unit tests. The stateful runtime is what makes Vest different.

import { create, enforce, test } from 'vest';

const suite = create(data => {
  test('username', 'Username is required', () => {
    enforce(data.username).isNotBlank();
  });

  test('username', 'Username must be at least 3 characters', () => {
    enforce(data.username).longerThanOrEquals(3);
  });

  test('username', 'Username is already taken', async ({ signal }) => {
    const response = await checkUsername(data.username, { signal });
    enforce(response.available).isTruthy();
  });
});

// Run only username tests and retain previous results for every other field.
const result = suite.only('username').run(formData);

result.isPending('username');
result.hasErrors('username');

// Await the current async run when final completion matters.
await result;

Why Vest?

  • Incremental execution: Validate a field, group, or step without rerunning everything.
  • Retained validation state: A focused run updates part of the existing result instead of replacing it.
  • Race-safe async: Track pending work, cancel obsolete requests, and ignore stale completions.
  • Real workflow primitives: Model dependent fields, conditional sections, warnings, optional values, groups, and dynamic lists.
  • Client and server continuity: Run statelessly on the server and resume full validation state in the browser.
  • Framework independence: Use the same suite with React, Vue, Svelte, Angular, vanilla JavaScript, or Node.js.
  • TypeScript and schemas: Infer typed inputs and parsed outputs with Enforce schemas.
  • Standard Schema interoperability: Pass suites and Enforce rules to compatible tools while keeping run() and runStatic() as Vest's execution APIs.
  • Familiar, testable rules: Keep business validation outside UI components in suites that are easy to unit-test.

Where Vest fits

LayerResponsibilityTypical tools
Form stateValues, registration, touched state, submissionReact Hook Form, Formik
Data boundaryParse and protect a complete payloadZod, Valibot, Ajv, Enforce schemas
Validation stateDecide what runs now, retain results, coordinate async workVest

These layers are complementary. A common architecture uses a form manager for input mechanics, Vest for progressive interaction, and a schema validator for the final submitted boundary.

Where Vest works well

Vest works well for:

  • async username, email, inventory, coupon, or eligibility checks;
  • onboarding and multi-step workflows;
  • linked fields and cross-field business rules;
  • warnings that should not block submission;
  • optional and conditional sections;
  • dynamic lists of travelers, products, or addresses;
  • rules shared between browser and server;
  • SSR workflows that should not validate everything twice.

For a trivial synchronous form or a one-shot API parse, native HTML validation or a schema validator may be all you need.

Installation

npm i vest

Start here

Contributing

Contributions are welcome. See CONTRIBUTING.md.

form
forms
form-validation
hacktoberfest
javascript
react-validation
react-validation-library
svelte-validation
typescript
unit-testing
validation
validation-library
vue-validation

Project health

Overall

4.4/10

Maintained

10/10

Code review

0/10
OpenSSF Scorecard

npm

Latest release

6.3.4 · Oct 3, 2026

Releases this year

15

Significant stargazers

EGOIST

13,581 followers · starred Dec 2023

Naor Peled

108 followers · starred Mar 2026

Marco Ippolito

465 followers · starred Dec 2023

Michael Stramel

110 followers · starred Jul 2021