Schemas
Import Pema's callable default export:
import p from "pema";p(schema) normalizes schema shorthand. Existing Pema schemas remain schemas;
primitive literals become literal schemas; constructors validate instances;
one-member arrays describe arrays, other arrays describe tuples; and object
shapes become object schemas.
const Settings = p({
theme: p.union("light", "dark"),
retries: p.u8,
});
const Names = p([p.string]);
const Pair = p([p.string, p.number]);
const Enabled = p(true);Prefer p({...}) for object schemas. The equivalent p.object(...) factory is
available for completeness, alongside explicit factories such as p.tuple(...)
and p.literal(...) when they make intent clearer.
Parse and infer
Every ordinary schema has parse(value). It returns the parsed value or throws
a ParseError. The compile-time output is available through schema.infer:
const Port = p.u16;
type Port = typeof Port.infer; // number
const port = Port.parse(8080);Object schemas additionally expose input, which accounts for fields supplied
by defaults and optional fields:
const Config = p({
host: p.string.default("localhost"),
port: p.u16,
});
type ConfigInput = typeof Config.input;
// { host?: string; port: number }Public type helpers include Schema, NormalizeSchema,
NormalizeSchemaObject, Parsed and Serialized. Prefer typeof schema.infer for an application's parsed value unless a generic API needs the
lower-level types.
Optional and default values
optional() accepts undefined and omits an undefined object property from the
parsed output. default(value) substitutes a value, or calls a function, when
the input is undefined.
const Preferences = p({
nickname: p.string.optional(),
locale: p.string.default("en"),
created: p.date.now(),
});These produce OptionalType and DefaultType wrappers. For Stores, a wrapper
is persistent only when its inner schema is Storable.
Derived values
derive() runs after successful parsing and changes the inferred output:
const FullName = p({
first: p.string,
last: p.string,
}).derive(({ first, last }) => `${first} ${last}`);Derived schemas are validation-only and are not direct Store fields. Use
p.async() for asynchronous object derivation.
Strict and loose parsing
Pema is strict by default. Use p.loose when a type supports coercing web input:
p.u16.parse("8080"); // throws
p.loose.u16.parse("8080"); // 8080
p.loose.boolean.parse("true"); // trueEvery factory is present under p.strict and p.loose, but coercion only
changes behavior for types that define it. strict does not reject undeclared
object keys; use object closed() for that policy.
Primitive checks
Primitive schemas support check(predicate, message):
const Even = p.u32.check(value => value % 2 === 0, "Expected an even number");The predicate runs after type parsing and coercion. A false result produces an
invalid_format issue.
Schema metadata
Ordinary schemas expose toJSON(). Primate uses serialized schema metadata for
framework integration, but it is not a lossless representation of every
validator, transform, predicate, derived function or object policy. Do not use
it as a general-purpose schema persistence format.