Important: This documentation covers Yarn 1 (Classic).
For Yarn 2+ docs and migration guide, see yarnpkg.com.

Package detail

conformal

marcomuser354MIT2.1.2TypeScript support: included

Type-safe form submissions for the modern web.

formdata, submission, schema, typescript

readme

Conformal

Type-safe form submissions for the modern web.

Conformal helps you work with native FormData. It solves two major pain points:

  • Strongly typed FormData parsing – Turn native FormData into real objects with full TypeScript inference (nested objects and arrays with dot/bracket notation).
  • Canonical submission flow – A single Submission object that preserves raw input, separates field vs. form errors, and standardizes the success/error states.

Works everywhere: In browsers, Node.js, and edge runtimes with React, Vue, Svelte, or vanilla JavaScript.

Table of Contents

Getting Started

Install Conformal via npm or the package manager of your choice:

npm install conformal

Here's a quick example showing how Conformal handles form validation with a user registration form:

import { parseFormData } from "conformal";
import * as z from "zod";

// Tip: Use conformal's coerce functions for form input preprocessing
const schema = z.object({
  name: z.string().min(2, "Name must be at least 2 characters"),
  email: z.email("Invalid email address"),
  age: z.coerce.number().min(18, "Must be at least 18 years old"),
  acceptTerms: z.coerce.boolean(),
});

// In your form action or handler
const result = parseFormData(schema, formData);
const submission = result.submission();

if (submission.status === "success") {
  // submission.value is fully typed: { name: string, email: string, age: number, acceptTerms: boolean }
  console.log("User registered:", submission.value);
} else {
  // submission.fieldErrors contains validation errors: { email: ["Invalid email address"] }
  console.log("Validation errors:", submission.fieldErrors);
  // submission.input preserves the raw user input for re-display
  console.log("User input:", submission.input);
}

That's it! Conformal automatically handles FormData parsing, type coercion, and provides a clean submission interface.

Live Examples

API Reference

Functions

  • parseFormData - Parse FormData with schema validation and get Submission object
  • decode - Convert FormData to structured objects (no validation)
  • serialize - Transform typed values back to form-compatible strings
  • getPath - Safely access nested values using dot/bracket notation
  • setPath - Immutably set nested values using dot/bracket notation
  • coerceX - A set of coercion functions for use with schema libraries

Types

  • Submission - Standardized submission result with success/error states
  • PathsFromObject - Type utility to extract all possible object paths

Valibot Utilities

⚠️ Experimental: These utilities are still in development and may change.

License

Conformal is licensed under the MIT License.

changelog

conformal

2.1.2

Patch Changes

2.1.1

Patch Changes

  • #39 76d370d Thanks @marcomuser! - Align coerceNumber invalid input handling

  • #39 76d370d Thanks @marcomuser! - Refactored valibot utilities from schemas to composable coercion pipes for form input preprocessing.

2.1.0

Minor Changes

  • #35 3224bd7 Thanks @marcomuser! - Add coerce functions

    • Add coerceString, coerceNumber, coerceBigint, coerceBoolean, coerceDate, coerceFile, coerceArray functions
    • These utilities help convert form input values to their expected types
    • Essential for building custom schema implementations (like zod preproccessors or valibot transforms)
  • #35 3224bd7 Thanks @marcomuser! - Deprecate zod utilities

    • Mark conformal/zod utilities as deprecated
    • Zod's z.preprocess returns a ZodPipe which doesn't allow method chaining, making these utilities less useful than expected
    • Zod utilities will be removed in the next major release
    • Users can migrate to using z.preprocess with the new coerce functions directly:
    import * as z from "zod";
    import { coerceNumber } from "conformal";
    
    z.preprocess(coerceNumber, z.number().min(5));
  • #35 3224bd7 Thanks @marcomuser! - Add valibot schemas

    • Add conformal/valibot subpath with valibot utilities
    • Provides string, number, boolean, date, bigint, picklist, file, array schemas
    • Uses conformal's coerce functions for automatic form input preprocessing
    • Fully compatible with valibot and can be mixed with regular valibot schemas
    • Marked as experimental - API may change

Patch Changes

2.0.0

Major Changes

  • #29 cc831d5 Thanks @marcomuser! - ## Breaking Changes

    • Rename parse to decode: The parse function has been renamed to decode to better reflect its purpose of decoding FormData into structured objects. This is a pure data transformation function with no validation.
    • Rename parseWithSchema to parseFormData: The parseWithSchema function has been renamed to parseFormData to be more specific about its input type and purpose. This function parses and validates FormData against a schema.
  • #29 cc831d5 Thanks @marcomuser! - ## Breaking Changes

    • Upgrade type-fest to v5: This release upgrades to type-fest v5, which requires TypeScript 5.9+ and Node.js v20+. Users will need to upgrade their TypeScript and Node.js versions to continue using this library.

1.4.0

Minor Changes

  • #25 22a44cb Thanks @marcomuser! - Enhance zod field schemas with array support and improved error handling
    • Add zf.array() with FormData-friendly preprocessing for multiselect/multicheckbox handling (single values become single-item arrays, multiple values stay arrays, empty strings become empty arrays)
    • Improve zf.bigint() with try-catch for graceful error handling to avoid runtime exceptions
    • Improve zf.date() with invalid date detection
    • Export zf.object() for convenient access alongside other zod field schemas

1.3.1

Patch Changes

1.3.0

Minor Changes

1.2.1

Patch Changes

1.2.0

Minor Changes

1.1.0

Minor Changes

  • #5 54a6604 Thanks @marcomuser! - Added PathsFromObject type to package exports. Fixed legacy node10 resolution.