Yup:JavaScript 里做数据校验,用它就够了
Yup:JavaScript 里做数据校验,用它就够了

Yup 在 GitHub 上有 23.6K Star,是一个 JavaScript/TypeScript 的数据校验库。它的核心工作就一件事:定义数据的形状,然后在运行时检查输入是否符合这个形状。
前端表单提交、后端接口入参、配置文件解析,这些场景都离不开数据校验。Yup 的做法是让你用链式调用的方式把校验规则写出来,然后扔一个值进去,要么通过,要么报错。
能做什么
Yup 支持常见的数据类型:string、number、boolean、date、array、object、tuple。每种类型都有一套内置的校验方法。
举个例子,定义一个用户对象的校验规则:
import { object, string, number, date } from 'yup';
let userSchema = object({
name: string().required(),
age: number().required().positive().integer(),
email: string().email(),
website: string().url().nullable(),
createdOn: date().default(() => new Date()),
});
写法很直白:string().required() 就是必填字符串,number().positive().integer() 就是正整数。链条可以任意组合,从简单到复杂的校验规则都能表达。
拿到数据之后调 validate 方法:
let user = await userSchema.validate(inputData);
如果数据不合法,直接抛 ValidationError,错误信息里包含字段路径和具体原因。
类型转换
Yup 不只是校验,还能做类型转换。从 JSON 或表单拿到的数据经常是字符串,Yup 可以帮你转成正确的类型:
let parsedUser = userSchema.cast({
name: 'jimmy',
age: '24',
createdOn: '2014-09-23T19:25:25Z',
});
// { name: 'jimmy', age: 24, createdOn: Date }
age 从字符串 '24' 变成了数字 24,createdOn 从 ISO 字符串变成了 Date 对象。这个能力在处理 API 响应或表单数据时很实用。
还可以自定义转换逻辑:
let reversedString = string()
.transform((currentValue) => currentValue.split('').reverse().join(''))
.cast('dlrow olleh'); // "hello world"
转换函数组成管道,前一个的输出是后一个的输入。
TypeScript 支持
Yup 的 TypeScript 支持做得很到位。可以从 schema 直接推导出静态类型:
import { InferType } from 'yup';
type User = InferType<typeof userSchema>;
// {
// name: string;
// age: number;
// email?: string | undefined
// website?: string | null | undefined
// createdOn: Date
// }
反过来也行,先定义 TypeScript 类型,再写 schema,让 Yup 检查两者是否一致。这样 schema 和类型之间的同步问题就解决了。
自定义校验
内置方法不够用的时候,可以用 test 方法加自定义规则:
string().test(
'is-james',
(d) => `${d.path} is not James`,
(value) => value == null || value === 'James',
);
第一个参数是校验名称,第二个是错误信息,第三个是校验函数。校验函数返回 true 就通过,返回 false 就报错。
条件校验用 when 方法,可以根据某个字段的值动态调整另一个字段的规则:
string().when('otherField', {
is: (val) => val > 0,
then: (schema) => schema.required(),
otherwise: (schema) => schema.optional(),
});
异步校验
Yup 内置了异步校验的支持。校验函数可以返回 Promise,比如去后端检查用户名是否已占用:
string().test('unique', '用户名已存在', async (value) => {
const res = await checkUsername(value);
return res.available;
});
调用 validate 本身就是异步的,返回 Promise,可以直接 await。
错误处理
校验失败时抛出的 ValidationError 包含详细信息:错误消息、字段路径、输入值。可以通过 inner 属性拿到所有字段的错误(对象校验时),也可以用 validateAt 只校验某个嵌套路径。
错误消息支持国际化,可以自定义模板或直接替换消息函数。

兼容 Standard Schema
Yup 支持 Standard Schema 规范。这意味着用 Yup 定义的 schema 可以被其他兼容 Standard Schema 的工具直接使用,不用额外适配。
适合谁用
用 JavaScript 或 TypeScript 做前后端开发的人,只要涉及表单校验、API 入参校验、配置文件解析,都可以考虑 Yup。它跟 React Hook Form、Formik 等表单库的配合也很成熟。如果你已经在用 Zod 想换个口味,Yup 的 API 设计风格不同,但功能覆盖面差不多。
ript 做前后端开发的人,只要涉及表单校验、API 入参校验、配置文件解析,都可以考虑 Yup。它跟 React Hook Form、Formik 等表单库的配合也很成熟。如果你已经在用 Zod 想换个口味,Yup 的 API 设计风格不同,但功能覆盖面差不多。
更多推荐
所有评论(0)