使用 Zod 于运行时检验类型
前言
Zod 是以 TypeScript 为首的 Schema 声明和验证库
不管是在 Astro、tRPC、React Hook Form、VeeValidate 背后都有使用到 Zod,这是个简单但充满威力的库值得去了解。
为什么你需要 Zod?
通常为了验证数据的正确性,我们会使用 JSDoc 或是 TypeScript 用于标注类型,虽然 TypeScript 可以帮助我们检查程序执行之前的类型,但在编译成 JavaScript 后还是仍有可能会于运行时因为数据与预期不符而出错,通常源自外部的数据(表单、网址、LocalStorage、API 响应)。这时候就是使用 Zod 的时间,协助在程序执行时检查数据的类型,以达到运行时的数据 Schema 检查。
示例:第三方 API 数据检测
举例来说一个 getPerson
函数会通过 ID 来获取不同人物的数据,就算可以替这个函数返回标注类型,在实际运作时仍就无法肯定 API 响应如同 TypeScript 内的 Person
类型:
interface Person = { name: string};
const getPerson = async (id: string): Person => { return await fetch('https://www.example.com/people/' + id + '.json') .then((res) => res.json());};
在使用 Zod 后,我们可以动态的检查 API 响应的数据是否符合 Person
类型,这么做不管在 TypeScript 还是运行时都能确保数据的正确性:
import { z } from 'zod';const Person = z.object({ name: z.string(),});// TS 类型: const getPerson: (id: string) => Promise<string>const getPerson = async (id: string) => { const response = await fetch('https://www.example.com/people/' + id + '.json').then((res) => res.json()); const result = Person.parse(response); // 经过 Zod 验证,确保数据符合 Person return result;};
try { getPerson(1);} catch (e) { console.error(e);}
示例:URL 参数验证
近期使用 Nuxt 框架有留意到这篇文章:Zod and Query String Variables in Nuxt,于是尝试在 Middleware(导航到特定页面前会执行的代码)安插 Zod 来检验用户传入的 URL query 参数正确性,优雅且简洁的解决了验证用户输入的问题!
// 用户要前往的页面 query 必须存在 order 且 filter 可选,否则跳转默认路径 (query: { order: 'DESC' })import { z } from 'zod';definePageMeta({ middleware: defineNuxtRouteMiddleware((to) => { const querySchema = z .object({ order: z.enum(['ASC', 'DESC']), filter: z.enum(['CURRENT', 'PAST', 'CURRENT,PAST']).optional(), }) .strict(); const defaultQuery = { order: 'DESC' }; const targetPath = to.fullPath; try { querySchema.parse(to.query); } catch (e) { // console.error(e) return navigateTo({ path: targetPath, query: defaultQuery }); } }),});
总结
从以上的范例可以观察到 zod,Zod 有许多验证方法可以使用,例如 z.string()
、z.number()
、z.boolean()
……等,这些方法可以组合使用来检查资料是否符合预期的类型,也可以自由定义错误时抛出的讯息,更多可以参考 Zod 文件即可,可以到延伸阅读了解更多实际案例与习题。
延伸阅读
- You Might Be Using Typescript Wrong… - Theo - t3.gg
- Zod - TotalTypeScript
- Zod Tutorial - All 10 places for Zod in your React / Next.js app - ByteGrad