Skip to content

Common

All schemas contain some common methods.

The parse method takes a value parameter as input. If the value conforms to the schema, then the parsed value is returned with the appropriate type, otherwise an exception containing a messages method is thrown. See the messages reference for details.

import * as p from '@vbudovski/paseri';
const schema = p.string();
try {
const parsedValue = schema.parse('foo');
// Do something with the `string`.
} catch (e) {
// Do something with the exception.
}

The safeParse method takes a value parameter as input. The result is a discriminated union with a boolean member ok. You can use it to extract the parsed value on success or get the error messages using result.messages(locale). Pass a locale (e.g. en) to get human-readable strings; calling without a locale returns the raw issue codes.

import * as p from '@vbudovski/paseri';
import { en } from '@vbudovski/paseri/locales';
const schema = p.string();
const result = schema.safeParse('foo');
if (result.ok) {
// Do something with the `result.value`.
} else {
// Do something with the `result.messages(en)`.
}

Allow any schema to accept undefined as a valid value.

import * as p from '@vbudovski/paseri';
const schema = p.string().optional();
const result = schema.safeParse(undefined);
if (result.ok) {
// result.value is of type `string | undefined`.
}

To substitute a value when the input is undefined, follow .optional() with .default(value).

import * as p from '@vbudovski/paseri';
const schema = p.number().optional().default(123);
const result = schema.safeParse(undefined);
if (result.ok) {
// result.value is of type `number`, equal to 123.
}

Allow any schema to accept null as a valid value.

import * as p from '@vbudovski/paseri';
const schema = p.string().nullable();
const result = schema.safeParse(null);
if (result.ok) {
// result.value is of type `string | null`.
}

Chain schemas to convert data types. The chain method takes the target schema as the first argument, and a transformer function as the second argument.

import * as p from '@vbudovski/paseri';
const schema = p.string().chain(p.bigint(), (value) => {
try {
return p.ok(BigInt(value));
} catch {
return p.err('invalid_bigint');
}
});
// Number.MAX_SAFE_INTEGER + 1 as a string.
const result = schema.safeParse('9007199254740992');
if (result.ok) {
// result.value is of type `bigint`.
}

err accepts an optional second argument, params, for forwarding placeholder values to the matching locale entry.

import * as p from '@vbudovski/paseri';
const schema = p.string().chain(p.number(), (value) => {
const n = Number(value);
if (Number.isNaN(n)) {
return p.err('not_a_number', { input: value });
}
return p.ok(n);
});

Add a custom check to any schema. The predicate runs on the parsed value and if it fails, an error is emitted at the given path. Multiple .refine() calls short-circuit on the first failure.

import * as p from '@vbudovski/paseri';
const schema = p
.object({
password: p.string(),
confirm: p.string(),
})
.refine((value) => value.password === value.confirm, {
code: 'password_mismatch',
path: ['confirm'],
});

The code is required. path defaults to the root ([]) and accepts string or number segments. The optional params object supplies placeholder values to the matching locale entry.

You can use the Infer type to determine the result type of any schema. This is useful, because you don’t want to manually define a type that could easily get out of sync with the schema definition.

import * as p from '@vbudovski/paseri';
const schema = p.object({
foo: p.string(),
bar: p.number(),
})
type MySchema = p.Infer<typeof schema>;
// MySchema will be { foo: string, bar: number }.

Paseri also provides an interface that’s compatible with Standard Schema 🔗. This makes it possible to use Paseri with a number of tools and frameworks without having to write custom wrappers.