Composition and special schemas
Unions and literals
p.union(...members) tries each normalized member and accepts the first schema
that parses. A union requires at least two members.
const Theme = p.union("light", "dark");
const Identifier = p.union(p.u32, p.uuid);UnionType supports optional() and default(). When every branch fails it
produces one invalid_type issue describing the union.
p.literal(value) creates LiteralType for a string, number or boolean. Passing
one of those values directly to callable p is equivalent.
Null and undefined
p.null and p.undefined accept exactly those values and return NullType and
UndefinedType. Compose them with a union when nullability is part of the
runtime contract:
const Name = p.union(p.string, null);Use optional() when absence or undefined is the intended object-input
behavior.
Predicates
p.is(predicate) creates IsType from a TypeScript type guard:
type Point = { x: number; y: number };
const Point = p.is((value): value is Point => {
if (typeof value !== "object" || value === null) return false;
const point = value as Record<string, unknown>;
return typeof point.x === "number" && typeof point.y === "number";
});The predicate is the validation contract. IsType supports optional() and
default() but does not define a Store datatype.
Primitive schemas offer check() when a type has already been parsed and only
an additional boolean condition is needed.
Class instances
p.constructor(Class) creates ConstructorType and accepts instances of that
class or its subclasses:
class Token {}
const TokenSchema = p.constructor(Token);Callable p(Token) is equivalent. Constructor schemas support optional() and
default() and are validation-only.
Unchecked values
p.pure<T>() supplies a static TypeScript type but returns every runtime input
unchanged. p.unknown is its unknown-typed counterpart. Neither validates the
value:
const External = p.pure<{ id: string }>();
External.parse(42); // accepted and typed as { id: string }Use these only at a boundary that is already trusted. PureType and
UnknownType are not Store fields.
Functions and symbols
p.function accepts functions and returns FunctionType; p.symbol accepts
symbols. These schemas are useful for configuration and in-memory contracts,
but cannot be persisted directly by a Store.
Most schemas on this page are validation-only. For structured persistent data,
use p.json(inner) when the parsed value is JSON-compatible.