Unions
联合(union)代表一种逻辑“或”的关系。你可以在你的模式(schema)中应用这个概念,使用 union 和 variant。对于可辨识联合(discriminated unions),你使用 variant,在所有其他情况下,你使用 union。
union 模式
union 模式函数可以在你以数组形式传入的任意数量的模式之间创建“或”的关系。验证时,该模式返回第一个成功验证的模式的结果。
import * as v from 'valibot';
// TypeScript
type Union = string | number;
// Valibot
const UnionSchema = v.union([v.string(), v.number()]);
如果一个错误的输入可以根据数据类型唯一地分配给其中一个模式,则返回该模式的结果。否则,会返回一个包含每个模式问题的通用问题。这是库中的一个特例,因为 union 的问题可能相互矛盾。
如果输入是 null 而不是字符串或数字,则会返回以下问题。由于在这种情况下输入无法与任一模式关联,因此两个模式的问题都会作为子问题返回。
[
{
kind: 'schema',
type: 'union',
input: null,
expected: 'string | number',
received: 'null',
message: 'Invalid type: Expected string | number but received null',
issues: [
{
kind: 'schema',
type: 'string',
input: null,
expected: 'string',
received: 'null',
message: 'Invalid type: Expected string but received null',
},
{
kind: 'schema',
type: 'number',
input: null,
expected: 'number',
received: 'null',
message: 'Invalid type: Expected number but received null',
},
],
},
];
variant 模式
为了更好的性能、更强的类型安全和更具针对性的问题输出,你可以为可辨识联合使用 variant。因此,只要有可能,我们都建议使用 variant 而非 union。可辨识联合是对象之间的“或”关系,可以通过一个特定的键来区分。
当你调用模式函数时,首先指定辨别器键(discriminator key)。这个键用于根据输入确定要使用的验证模式。对象模式(以数组形式)作为第二个参数紧随其后。
import * as v from 'valibot';
const VariantScheme = v.variant('type', [
v.object({
type: v.literal('foo'),
foo: v.string(),
}),
v.object({
type: v.literal('bar'),
bar: v.number(),
}),
]);
对于非常复杂的数据集,多个 variant 模式也可以相互深度嵌套。