如何基于外部条件在Yup中添加验证规则并解决TS报错?
基于外部变量动态构建Yup验证规则并解决TypeScript报错
一、.when不适用于外部变量的替代方案
你尝试用.when([])依赖外部变量,但Yup的.when设计初衷是关联表单内部字段,直接用它处理外部变量会触发TypeScript类型错误。更合适的做法是用test方法自定义验证逻辑:
const schema = yup.object().shape({ FirstField: yup.string().required(), SecondFiled: yup.string().required(), ConditionalField: yup.string().test( 'conditional-required', 'Please input str2', (value) => { // 直接引用外部变量condition if (condition) { // condition为true时,字段允许为空 return value == null || typeof value === 'string'; } else { // condition为false时,字段必须非空 return typeof value === 'string' && value.trim().length > 0; } } ) });
test方法灵活性更高,完全适配外部变量的条件判断,同时TypeScript能正确推导类型。
二、动态添加验证字段的TypeScript问题解决
你遇到的两个报错——属性未定义和ArraySchema泛型参数缺失,可以通过以下两种方式解决:
方式1:预定义完整类型
先明确表单所有可能的字段类型,再用Record约束规则对象的类型,同时补全ArraySchema的泛型参数:
import * as yup from 'yup'; // 定义表单值的类型,包含所有可能字段 type FormValues = { signedAt: string; startsAt: string; endsAt: string; acceptancePlaces?: string[]; }; // 用Record约束规则对象的键为FormValues的键,值为Yup Schema const rules: Record<keyof FormValues, yup.Schema> = { signedAt: yup.string().required('请填写签署时间'), startsAt: yup.string().required('请填写开始时间'), endsAt: yup.string().required('请填写结束时间'), // 初始给可选字段设为非必填的混合类型,后续覆盖 acceptancePlaces: yup.mixed().notRequired() }; // 根据外部条件更新规则 if (props.documentSet && !props.documentSet.regime) { rules.acceptancePlaces = yup.array(yup.string()) .required('请选择接收地点') .min(1, '至少选择一个接收地点') as yup.ArraySchema<string[], yup.AnyObject, string[], string[]>; } const schema = yup.object().shape(rules);
方式2:动态构建shape配置
直接用Record<string, yup.Schema>作为配置对象的类型,允许自由添加字段,同时用类型断言解决ArraySchema的泛型问题:
import * as yup from 'yup'; // 初始化基础字段规则 const shapeConfig: Record<string, yup.Schema> = { signedAt: yup.string().required('请填写签署时间'), startsAt: yup.string().required('请填写开始时间'), endsAt: yup.string().required('请填写结束时间') }; // 根据外部条件添加字段规则 if (props.documentSet && !props.documentSet.regime) { shapeConfig.acceptancePlaces = yup.array(yup.string()) .required('请选择接收地点') .min(1, '至少选择一个接收地点') as yup.ArraySchema<string[], yup.AnyObject, string[], string[]>; } const schema = yup.object().shape(shapeConfig);
三、条件显示字段的完整示例
假设表单中secondName根据外部props条件显示/隐藏,对应的验证规则动态添加:
import * as yup from 'yup'; export default { props: { needSecondName: Boolean }, setup(props) { // 构建表单规则配置 const formShape: Record<string, yup.Schema> = { firstName: yup.string().required('请填写名字') }; // 根据条件添加secondName的验证规则 if (props.needSecondName) { formShape.secondName = yup.string().required('请填写姓氏'); } // 创建最终验证schema const schema = yup.object().shape(formShape); return { schema }; } };
当needSecondName为true时,schema包含secondName的必填验证;为false时,schema不包含该字段,验证时不会检查它,完全匹配字段的条件显示逻辑。
内容的提问来源于stack exchange,提问作者Victor
相关产品推荐
相关产品推荐

