The adapter problem it solves
By 2026 the TypeScript ecosystem has several excellent runtime validation libraries — Zod, Valibot, ArkType, TypeBox — and that abundance created a headache for *library authors*. If you build a form library, a router, or an ORM and want it to accept "a schema," which one do you support? Historically you either picked a favorite (locking out users of the others) or wrote a separate adapter for each. Every integration was N libraries × M frameworks of glue.
[Standard Schema](https://standardschema.dev/) is the fix: a minimal, shared interface — designed jointly by the creators of Zod, Valibot, and ArkType — that every validation library implements. A tool that speaks Standard Schema accepts *any* compliant library with zero adapters. If you've read JSON Schema vs Zod vs Pydantic, this is the layer that lets those TypeScript validators become drop-in interchangeable.
What the spec actually is
Standard Schema is deliberately tiny. A compliant schema exposes a single hidden property, ~standard, containing a version, the vendor name, and one validate function. That's the whole contract:
interface StandardSchemaV1<Input, Output> {
readonly "~standard": {
readonly version: 1;
readonly vendor: string; // "zod" | "valibot" | "arktype" | ...
readonly validate: (value: unknown) =>
| { value: Output } // success
| { issues: ReadonlyArray<{ message: string; path?: PropertyKey[] }> }; // failure
readonly types?: { input: Input; output: Output };
};
}The validate function takes an unknown value and returns either a value (on success) or an issues array (on failure) — never throws for validation errors. The types field carries the TypeScript input/output types for inference. Because the surface is so small, libraries implement it without changing their own APIs, and consumers depend on the interface, not on any one library.
Using it as a library author
If you're building something that accepts a schema, you type the parameter as StandardSchemaV1 and call validate. You now support every compliant library at once:
import type { StandardSchemaV1 } from "@standard-schema/spec";
async function parse<T extends StandardSchemaV1>(
schema: T,
input: unknown,
): Promise<StandardSchemaV1.InferOutput<T>> {
const result = await schema["~standard"].validate(input);
if (result.issues) {
throw new Error(JSON.stringify(result.issues, null, 2));
}
return result.value;
}A user can now pass a Zod schema, a Valibot schema, or an ArkType schema to your parse — you wrote no adapters, and you don't even import the validation libraries. This is why routers, form libraries, ORMs, and AI SDKs adopted it quickly: one integration, whole ecosystem.
Using it as an app developer
The payoff for application code is portability without rewrites. Because the libraries share an interface, you can:
- Switch libraries — start with Zod for its ecosystem, later move a bundle-sensitive edge function to Valibot — while every Standard-Schema-aware tool keeps working.
- Mix libraries in one codebase, using each where it fits, and pass all of them to the same utilities.
- Depend on tools, not vendors — pick a form library because it's good, not because it happens to support your validator.
What it is *not*
Standard Schema is a runtime interface, not a serialization format. It doesn't define how to store or share a schema as data — that's what JSON Schema is for. The two are complementary: JSON Schema is the portable, language-agnostic *document* format for describing data shapes across systems; Standard Schema is the in-process *TypeScript interface* that lets validation libraries interoperate. Many of these libraries can also *emit* JSON Schema (Zod, TypeBox), so you often use both — Standard Schema for library interop, JSON Schema when a shape must cross a language or service boundary.
For the libraries that implement it, see the head-to-head in Zod v4 vs Valibot vs ArkType, and to turn existing JSON into one of these schemas, try the JSON to Zod tool.