使用Yup验证非互斥正则规则并返回独立错误信息
为Formik+Yup实现手机号字段多规则独立错误提示验证器
问题分析
链式调用matches()会被先执行的兜底规则拦截,导致后续更具体的规则无法触发对应错误。要实现每条规则返回独立错误,需用yup.test()逐个校验,或通过自定义扩展方法封装校验逻辑,同时解决TypeScript类型报错问题。
解决方案步骤
1. 扩展Yup的TypeScript类型声明
自定义方法前需扩展StringSchema类型,避免TS报错。创建yup.d.ts文件或在代码中添加类型声明:
declare module 'yup' { interface StringSchema<TType extends string | undefined = string | undefined, TContext extends AnyObject = AnyObject, TOut extends string | undefined = TType> { noLetters(message?: string): StringSchema<TType, TContext, TOut>; noPeriods(message?: string): StringSchema<TType, TContext, TOut>; noInvalidSymbols(message?: string): StringSchema<TType, TContext, TOut>; } }
2. 封装自定义验证方法
用yup.addMethod封装四条规则的校验逻辑,每个方法对应一条规则,返回独立错误信息:
import * as yup from 'yup'; // 禁止ASCII字母 yup.addMethod(yup.string, 'noLetters', function(message = '手机号不能包含英文字母') { return this.test('no-letters', message, function(value) { if (!value) return true; // 空值交由required校验(按需添加) return !/[A-Za-z]/.test(value); }); }); // 禁止句号 yup.addMethod(yup.string, 'noPeriods', function(message = '手机号不能包含句号') { return this.test('no-periods', message, function(value) { if (!value) return true; return !/\./.test(value); }); }); // 禁止非允许的符号(仅允许数字、空格、()、-) yup.addMethod(yup.string, 'noInvalidSymbols', function(message = '手机号不能包含除()、-、空格外的其他符号') { return this.test('no-invalid-symbols', message, function(value) { if (!value) return true; return !/[^\s\d()\-]/.test(value); }); });
3. 构建表单验证Schema
在Formik的Schema中直接调用自定义方法,按顺序校验,触发对应规则的独立错误:
const phoneValidationSchema = yup.object().shape({ phoneNo: yup.string() .min(6, '手机号长度至少为6位') .max(35, '手机号长度最多为35位') .noLetters() .noPeriods() .noInvalidSymbols() // .required('手机号不能为空') // 按需添加必填校验 });
效果说明
- 输入
111222a→ 触发「手机号不能包含英文字母」 - 输入
111222.→ 触发「手机号不能包含句号」 - 输入
111$222→ 触发「手机号不能包含除()、-、空格外的其他符号」 - 所有校验按顺序执行,不会被兜底规则提前拦截,确保每条违规都返回对应错误提示。
内容的提问来源于stack exchange,提问作者Mike S.
相关产品推荐
相关产品推荐

