Custom rules & schemas
Not enough built-in rules? A custom rule is just a function. For complex cases you can write your own schema.
A rule with check
The easiest way is check. Wrap it in a function to reuse it and pass a message:
ts
import { check, pipe, number, string } from 'tinyval';
const even = (msg = 'Must be even') => check<number>((v) => v % 2 === 0, msg);
const noSpaces = (msg = 'No spaces allowed') => check<string>((v) => !/\s/.test(v), msg);
pipe(number(), even());
pipe(string(), noSpaces());The second argument gives access to sibling fields (parent) and all data (root):
ts
const after = (field: string, msg = 'Must be later') =>
check<Date>((v, { parent }) => v > (parent as any)[field], msg);
object({
start: coerce.date(),
end: pipe(coerce.date(), after('start')),
});An async rule
ts
const unique = (table: string) =>
checkAsync<string>(async (v) => !(await db.exists(table, v)), 'Already taken');
const Signup = object({ email: pipe(string(), email(), unique('users')) });
await validateAsync(Signup, body);More — checkAsync.
A custom schema
createSchema creates a schema from a validation function. The function returns the value (possibly transformed) or the result of fail(...). A schema for bigint:
ts
import { createSchema, fail, isEmpty, type Message } from 'tinyval';
export const bigint = (msg?: Message) =>
createSchema<bigint>((value, ctx, path) => {
if (isEmpty(value)) return fail(ctx, path, 'required', msg);
if (typeof value !== 'bigint') return fail(ctx, path, 'bigint', msg);
return value;
});fail(ctx, path, code, msg?, params?)— records an error and returns a special marker.isEmpty(value)—trueforundefined,nulland''.- Add a text for your code via
setMessages:setMessages({ bigint: 'Must be a bigint' }). Otherwise theinvalidmessage is used.
A custom schema works everywhere: in object, array, pipe, optional, its type is inferred with Infer, and it supports Standard Schema.
See also
- check
- checkAsync
- preprocess — when you only need to prepare the input
- transform — when you need to change the output