Lzh on GitHub

这份指南解释了其他特殊的模式函数,例如 literalinstancecustomlazy,这些函数没有在其他指南中涵盖。

literal 模式

你可以使用 literal 来定义一个模式,它匹配特定的字符串、数字或布尔值。因此,这种模式非常适合表示字面量类型。用法很简单,只需将你想要匹配的值作为第一个参数传入即可。

import * as v from 'valibot';

const StringLiteralSchema = v.literal('foo'); // 'foo'
const NumberLiteralSchema = v.literal(12345); // 12345
const BooleanLiteralSchema = v.literal(true); // true

instance 模式

通过 blobdatemapset 等模式函数,Valibot 已经涵盖了最常见的 JavaScript 类。然而,可能还有很多你想要验证的类。为此,你可以使用 instance 模式函数。它将一个类作为第一个参数,并返回一个只匹配该类实例的模式。

import * as v from 'valibot';

const ErrorSchema = v.instance(Error); // Error
const UrlSchema = v.instance(URL); // URL

custom 模式

custom 模式函数稍微高级一些。它允许你根据一个自定义函数来定义一个匹配某个值的模式。当你需要定义一个无法用其他模式函数表达的模式时,就可以使用它。

这个函数接收要验证的值作为它的第一个参数,并且必须返回一个布尔值。如果函数返回 true,则该值被认为是有效的。否则,它被认为是无效的。

import * as v from 'valibot';

const PixelStringSchema = v.custom<`${number}px`>((input) =>
  typeof input === 'string' ? /^\d+px$/.test(input) : false);

lazy 模式

lazy 模式函数允许你定义递归模式。递归模式是引用自身的模式。例如,你可以用它来定义一个树状数据结构的模式。

由于 TypeScript 的限制,在这种情况下输入和输出类型无法自动推断。因此,你必须使用 GenericSchema 类型来显式指定这些类型。

import * as v from 'valibot';

type BinaryTree = {
  element: string;
  left: BinaryTree | null;
  right: BinaryTree | null;
};

const BinaryTreeSchema: v.GenericSchema<BinaryTree> = v.object({
  element: v.string(),
  left: v.nullable(v.lazy(() => BinaryTreeSchema)),
  right: v.nullable(v.lazy(() => BinaryTreeSchema)),
});

lazy 的另一个实际用例是为所有可能的 JSON 值定义模式。这些值是所有可以使用 JSON.stringify()JSON.parse() 进行序列化和反序列化的值。

import * as v from 'valibot';

type JsonData =
  | string
  | number
  | boolean
  | null
  | { [key: string]: JsonData }
  | JsonData[];

const JsonSchema: v.GenericSchema<JsonData> = v.lazy(() =>
  v.union([
    v.string(),
    v.number(),
    v.boolean(),
    v.null(),
    v.record(v.string(), JsonSchema),
    v.array(JsonSchema),
  ]));