从Zod迁移
从 Zod 迁移到 Valibot 在大多数情况下非常简单,因为两个 API 有很多相似之处。以下指南将帮助你逐步迁移,并指出重要的区别。
官方 Codemod
为了使迁移尽可能顺利,我们创建了一个官方的 Codemod,它可以自动将你的 Zod 模式迁移到 Valibot。只需将你的模式复制到此编辑器中并点击“播放”即可。
这个 codemod 仍处于测试阶段,可能无法涵盖所有边缘情况。如果你遇到任何问题或意外行为,请创建一个 issue。或者,你可以尝试自己修复问题并创建一个 pull request。你可以在这里找到源代码。
你很快也能在终端本地运行这个 codemod,一次性迁移整个代码库。敬请期待!
替换导入
安装 Valibot 后,第一件事是更新你的导入。只需将 Zod 的导入更改为 Valibot 的,并将所有 z. 替换为 v.。
// 改为
import * as v from 'valibot';
const Schema = v.object({ key: v.string() });
// 而不是
import { z } from 'zod';
const Schema = z.object({ key: z.string() });
重构代码
Zod 和 Valibot 之间最大的区别之一是你进一步验证给定类型的方式。在 Zod 中,你链式调用方法,如 .email 和 .endsWith。在 Valibot 中,你使用管道(pipelines)来做同样的事情。这是一个以模式开始,后面跟着多达 19 个验证或转换操作的函数。
// 改为
const Schema = v.pipe(v.string(), v.email(), v.endsWith('@example.com'));
// 而不是
const Schema = z.string().email().endsWith('@example.com');
由于 Valibot 的模块化设计,所有其他方法,如 .parse 或 .safeParse,也必须以稍微不同的方式使用。你通常将模式作为第一个参数传递,并将任何现有参数向右移动一个位置,而不是链式调用它们。
// 改为
const value = v.parse(v.string(), 'foo');
// 而不是
const value = z.string().parse('foo');
我们建议你阅读我们的心智模型指南,以理解 Valibot 模块化 API 的各个函数是如何协同工作的。
更改名称
大多数名称与 Zod 相同。但是,也有一些例外。下表显示了所有已更改的名称。
| Zod | Valibot |
|---|---|
and | intersect |
catchall | objectWithRest |
coerce | pipe, unknown 和 transform |
datetime | isoDate, isoDateTime |
default | optional |
discriminatedUnion | variant |
element | item |
enum | picklist |
extend | Object merging |
gt | gtValue |
gte | minValue |
infer | InferOutput |
int | integer |
input | InferInput |
instanceof | instance |
intersection | intersect |
lt | ltValue |
lte | maxValue |
max | maxLength, maxSize, maxValue |
min | minLength, minSize, minValue |
nativeEnum | enum |
negative | maxValue |
nonnegative | minValue |
nonpositive | maxValue |
or | union |
output | InferOutput |
passthrough | looseObject |
positive | minValue |
refine | check, forward |
rest | tuple |
safe | safeInteger |
shape | entries |
strict | strictObject |
strip | object |
superRefine | rawCheck, rawTransform |
其他细节
下面是一些在从 Zod 迁移到 Valibot 时可能会有用的更多细节。
对象和元组
为了指定对象或元组是应该允许还是禁止未知值,Valibot 使用不同的模式函数。Zod 则使用 .passthrough, .strict, .strip, .catchall 和 .rest 等方法。有关更多详细信息,请参阅对象和数组指南。
// 改为
const ObjectSchema = v.strictObject({ key: v.string() });
// 而不是
const ObjectSchema = z.object({ key: z.string() }).strict();
错误信息
对于个别错误信息,你可以向 Zod 传递一个字符串或一个对象。它还允许你区分“required”和“invalid_type”的错误信息。而 Valibot 你只需传递一个简单的字符串。
// 改为
const StringSchema = v.pipe(
v.string('Not a string'),
v.minLength(5, 'Too short')
);
// 而不是
const StringSchema = z.string({ invalid_type_error: 'Not a string' }).min(5, { message: 'Too short' });
强制类型转换
在 Zod 中,你可以使用 coerce 对象的方法来强制转换原始值。Valibot 中没有这样的对象或函数。相反,你使用带有 transform 操作的管道作为第二个参数。这迫使你显式定义输入,从而产生更安全的代码。
// 改为
const NumberSchema = v.pipe(v.unknown(), v.transform(Number));
// 而不是
const NumberSchema = z.coerce.number();
与上面示例中的 unknown 不同,我们通常建议使用特定的模式(如 string)来提高类型安全性。例如,这允许你在将其转换为数字之前,用 decimal 验证字符串的格式。
const NumberSchema = v.pipe(v.string(), v.decimal(), v.transform(Number));
异步验证
与 Zod 类似,Valibot 支持同步和异步验证。但是,API 有点不同。有关更多详细信息,请参阅异步指南。