欢迎,类型冒险家!🎩 TypeScript 很棒,对吧?它通过引入静态类型帮助我们更好地组织代码,避免令人烦恼的 bug。但是这里有个问题:TypeScript 只在编译时检查类型!😬 是的,一旦代码运行,无法保证外部数据(来自 API、用户等)会符合预期的结构。这就是 Zod 登场的时候,来拯救我们!🚀
在本文中,我们将探索为什么以及如何使用 Zod,这个允许你动态验证和类型化数据的库。从基本验证到复杂的数据结构,Zod 为你提供了在 TypeScript 中无妥协地保护数据的方法。让我们开始吧!🎉
Zod 是什么?🤔
Zod 是一个 TypeScript 模式验证库,可以实时验证你的数据。使用 Zod,你可以为任何类型的对象创建验证模式。想象一个返回不确定数据的 API:Zod 可以即时验证收到的数据是否符合预期类型。
Zod 的主要特点 💪
- 简单灵活:语法直观且富有表现力
- 验证和类型合二为一:无需在单独的类型和验证之间切换,Zod 全都处理!
- 即时反馈:当数据不符合模式时,立即获得详细错误信息
- 强大的 API:从简单验证到复杂转换,Zod 提供完整的 API
安装 Zod 📦
要开始使用,只需通过 npm 或 yarn 安装 Zod:
现在你已经准备就绪,让我们开始创建你的第一个 Zod 模式!
使用 Zod 创建基本模式 🎨
Zod 模式代表预期的数据结构。让我们以一个简单的例子开始,验证具有姓名、年龄和电子邮件地址的用户。
示例:基本验证
以下是如何为用户定义 Zod 模式 👤:
在这个例子中,Zod 会检查 userInput
是否符合 userSchema
定义的模式。如果一切正常,parse
返回验证后的数据。否则,它会抛出一个带有详细错误信息的错误。生产环境中不会有意外!🎉
条件类型和联合类型:处理多种情况 🔀
Zod 还可以通过条件类型处理复杂的模式。假设你有一个表单,用户可以是客户或管理员。以下是如何使用 Zod 定义这个模式。
示例:联合类型模式
在这个例子中,Zod 验证 adminUser
是 client
或 admin
,并检查每个角色所需的属性。很实用,对吧?👌
转换:同时验证和转换 🔄
有时,你想验证数据并同时转换它。Zod 可以轻松实现这一点,比如将字符串转换为数字。
示例:数据转换
这里,Zod 接受一个字符串("49.99"
)并将其转换为有效数字。
自定义验证 🛠️
Zod 还允许使用 .refine()
方法创建自定义验证。假设你想验证密码是否符合特定标准,如最小长度和特殊字符的存在。
示例:密码验证
.refine()
方法允许添加自定义条件。在这里,Zod 检查密码是否符合定义的标准,如果不符合则提供具体的错误消息。
为什么选择 Zod?🌟
Zod 已成为 TypeScript 验证的必备工具,因为它:
- 完美结合验证和类型,无需增加复杂性
- 提供清晰直观的 API,即使对于复杂模式
- 提供易于理解和调试的错误信息
- 与 TypeScript 项目完美集成
总结
Zod 通过动态验证接收的数据,为 TypeScript 添加了额外的安全性和可靠性层。你可以安心休息,知道你的数据是健康且类型安全的。那么,准备好在下一个项目中尝试 Zod 了吗?😎
1import { z } from 'zod';
2
3// 用户模式
4const userSchema = z.object({
5 name: z.string(), // 名字必须是字符串
6 age: z.number().int().min(18), // 年龄必须是整数,最小 18
7 email: z.string().email(), // 必须是有效的电子邮件
8});
9
10// 输入数据示例
11const userInput = {
12 name: 'Alice',
13 age: 25,
14 email: 'alice@example.com',
15};
16
17// 数据验证
18try {
19 const validUser = userSchema.parse(userInput); // parse 返回验证后的数据
20 console.log('有效用户:', validUser);
21} catch (e) {
22 console.error('验证错误:', e.errors);
23}
1// 客户模式
2const clientSchema = z.object({
3 role: z.literal('client'),
4 preferences: z.array(z.string()), // 偏好设置数组
5});
6
7// 管理员模式
8const adminSchema = z.object({
9 role: z.literal('admin'),
10 accessLevel: z.number().min(1).max(5), // 访问级别 1-5
11});
12
13// 两种模式的联合
14const userSchema = z.union([clientSchema, adminSchema]);
15
16// 用户示例
17const adminUser = {
18 role: 'admin',
19 accessLevel: 3,
20};
21
22// 验证
23try {
24 const validUser = userSchema.parse(adminUser);
25 console.log('有效用户:', validUser);
26} catch (e) {
27 console.error('验证错误:', e.errors);
28}
1const passwordSchema = z
2 .string()
3 .min(8, { message: '密码至少需要 8 个字符' })
4 .refine((val) => /[A-Z]/.test(val), {
5 message: '密码必须包含至少一个大写字母',
6 })
7 .refine((val) => /[0-9]/.test(val), {
8 message: '密码必须包含至少一个数字',
9 });
10
11// 输入示例
12const passwordInput = 'Secure123';
13
14// 验证
15try {
16 const validPassword = passwordSchema.parse(passwordInput);
17 console.log('有效密码:', validPassword);
18} catch (e) {
19 console.error('验证错误:', e.errors);
20}