Skip to content

自定义规则与 Schema ​

内置规则不够用?自定义规则就是一个普通函数。对于复杂情况,还可以编写自己的 Schema。

用 check 编写规则 ​

最简单的方式是 check。把它包装成函数,便于复用和传入信息:

ts
import { check, pipe, number, string } from 'tinyval';

const even = (msg = '必须是偶数') => check<number>((v) => v % 2 === 0, msg);
const noSpaces = (msg = '不能包含空格') => check<string>((v) => !/\s/.test(v), msg);

pipe(number(), even());
pipe(string(), noSpaces());

第二个参数可以访问同级字段(parent)和全部数据(root):

ts
const after = (field: string, msg = '必须晚于开始时间') =>
  check<Date>((v, { parent }) => v > (parent as any)[field], msg);

object({
  start: coerce.date(),
  end: pipe(coerce.date(), after('start')),
});

异步规则 ​

ts
const unique = (table: string) =>
  checkAsync<string>(async (v) => !(await db.exists(table, v)), '已被占用');

const Signup = object({ email: pipe(string(), email(), unique('users')) });
await validateAsync(Signup, body);

更多内容见 checkAsync。

自定义 Schema ​

createSchema 用校验函数创建 Schema。函数返回值(可以是转换后的值)或 fail(...) 的结果。bigint 的 Schema 示例:

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?) —— 记录错误并返回一个特殊标记。
  • isEmpty(value) —— 对 undefined、null 和 '' 返回 true。
  • 通过 setMessages 为自定义代码添加文本:setMessages({ bigint: '必须是 bigint' })。否则使用 invalid 的信息。

自定义 Schema 可以在任何地方使用:object、array、pipe、optional,可以通过 Infer 推导类型,并且支持 Standard Schema。

另请参阅 ​