1
Core Execution & Parsing Engine
Validation is invoked directly via synchronous and asynchronous methods attached to every schema instance.
| Method |
Return Signature |
Behavior & Fail Mode |
| .parse(input) |
TOutput |
Synchronous. Throws ValidationError on invalid input or async pipelines.
|
| .safeParse(input) |
SafeParseResult<TOutput> |
Returns { success: true, data } or { success: false, error }.
|
| .parseAsync(input) |
Promise<TOutput> |
Asynchronous execution. Awaits all async transformations, refinements, and sub-schemas.
|
| .safeParseAsync(input) |
Promise<SafeParseResult> |
Non-throwing Promise resolving to a strongly typed discriminated union. Alias: .spa().
|
// Importing the unified namespace
import { infer,
type Infer }
from
"subatom-infer";
const User = infer.object({
id: infer.uuid(),
username: infer.string().min(3),
});
// Safe synchronous parsing
const result = User.safeParse({ id: "123e4567-e89b-12d3-a456-426614174000", username: "alex" });
if (result.success) {
console.log(result.data.username); // Typed as string
}
2
Primitives, Unit Types & String Validation API
Core Primitives & Singletons
infer.string()
infer.number()
infer.boolean()
infer.bigint()
infer.date()
infer.symbol()
infer.undefined()
infer.null()
infer.void()
infer.any()
infer.unknown()
infer.never()
infer.nan()
infer.literal("ACTIVE")
String Formatting & Constraints
infer.string()
.min(5).max(100).length(20)
.email().url().httpUrl()
.uuid().guid().cuid().cuid2()
.ulid().nanoid()
.regex(/^[a-z]+$/i)
.startsWith("sub_").endsWith("_node")
.includes("@")
.datetime().date().time().duration()
.ipv4().ipv6().hostname()
.trim().toLowerCase().toUpperCase()
3
Number & BigInt Validation Constraints
Number Schema Constraints
infer.number()
.int() // Integer only
.safe() // Safe IEEE-754 range
.finite() // Rejects Infinity
.positive() // > 0
.nonnegative() // >= 0
.negative() // < 0
.nonpositive() // <= 0
.min(1).max(100)
.gte(1).lte(100)
.gt(0).lt(101)
.multipleOf(5)
BigInt Schema Constraints
infer.bigint()
.positive() // > 0n
.nonnegative() // >= 0n
.negative() // < 0n
.nonpositive() // <= 0n
.min(100n)
.max(1000000n)
.multipleOf(10n)
4
Objects & Structural Policies
Objects offer manipulation primitives, structural modifiers, key policies, and recursive transformations.
const BaseUser = infer.object({
id: infer.uuid(),
name: infer.string(),
role: infer.enum(["admin", "user"]),
});
// Object Policy Modifiers
const StrictUser = BaseUser.strict(); // Rejects unrecognized keys
const LooseUser = BaseUser.passthrough(); // Retains unknown keys
const StrippedUser = BaseUser.strip(); // Default: strips extra properties
const CatchallUser = BaseUser.catchall(infer.boolean()); // Validates unknown keys
// Structural Composition & Transformations
const ExtendedUser = BaseUser.extend({ email: infer.email() });
const MergedSchema = BaseUser.merge(infer.object({ traceId: infer.string() }));
const PickedName = BaseUser.pick({ name: true });
const OmittedId = BaseUser.omit({ id: true });
const PartialUser = BaseUser.partial(); // All fields optional
const RequiredUser = PartialUser.required(); // All fields required
const DeepOptional = BaseUser.deepPartial(); // Recursively optional
const UserKeysEnum = BaseUser.keyof(); // Returns EnumSchema of keys
5
Collections: Arrays, Tuples, Records, Sets & Maps
Arrays & Fixed Tuples
// Array with length bounds
const Tags = infer.array(infer.string())
.min(1).max(10).nonempty();
// Tuples with positional schemas
const Coord = infer.tuple([
infer.number(),
infer.number(),
infer.number().optional()
]);
Records, Sets & Maps
// Dynamic Key-Value Map
const Config = infer.record(
infer.string().min(2),
infer.number()
);
// Native JS Set & Map instances
const Roles = infer.set(infer.string()).min(1);
const Lookup = infer.map(infer.uuid(), infer.boolean());
6
Combinators, Special Schemas & Recursive Types
Tagged & Untagged Unions
// Discriminated Union (O(1) matching)
const Event = infer.discriminatedUnion("type", [
infer.object({ type: infer.literal("click"), x: infer.number() }),
infer.object({ type: infer.literal("hover"), element: infer.string() })
]);
// Union & Intersection
const StrOrNum = infer.union([infer.string(), infer.number()]);
const Combined = infer.intersection(SchemaA, SchemaB);
Function, Promise, File & Lazy
// Function Schema
const AddFn = infer.function(
infer.tuple([infer.number(), infer.number()]),
infer.number()
);
// Promise, File & Recursive Lazy
const AsyncStr = infer.promise(infer.string());
const Upload = infer.file().max(5_000_000).mime("image/png");
const Node = infer.lazy(() => infer.object({
next: Node.optional()
}));
7
Modifiers, Pipelines, Codecs & Refinements
// 1. Modifiers & Defaults
const OptStr = infer.string().optional(); // string | undefined
const NullableNum = infer.number().nullable(); // number | null
const NullishDate = infer.date().nullish(); // Date | null | undefined
const DefaultPort = infer.number().default(3000);
const PrefaultVal = infer.string().prefault("anonymous");
const SafeValue = infer.number().catch(0);
// 2. Transformation Pipeline & Pipe
const StrToDate = infer.string().transform((val) => new Date(val));
const PipedValidation = infer.pipe(infer.string().min(2), infer.string().email());
// 3. Refinements & SuperRefine
const PasswordCheck = infer.object({
password: infer.string().min(8),
confirm: infer.string()
}).superRefine((data, ctx) => {
if (data.password !== data.confirm) {
ctx.addIssue({ code: "custom", message: "Passwords must match" });
}
});
// 4. Nominal Branding & Bidirectional Codecs
const UserIdSchema = infer.brand(infer.uuid(), "UserId");
const Base64Codec = infer.codec(
infer.string().transform((str) => Buffer.from(str, "base64")),
(buf: Buffer) => buf.toString("base64")
);
8
Coercion Engine & Error Formatting API
Primitive Coercion
infer.coerce.string()
infer.coerce.number().int()
infer.coerce.boolean()
infer.coerce.bigint()
infer.coerce.date()
// Automatically parses strings
infer.coerce.number().parse("42"); // 42 (number)
Error Tree Formatting
try {
UserSchema.parse(badInput);
} catch (err) {
// Form & field error record
err.flatten();
// Deeply nested issue tree
err.format();
// Pretty CLI string format
console.log(err.prettifyError());
}