闭包实现的柯里化函数天然支撑类型感知表单校验引擎——通过解耦校验逻辑与数据类型,使验证规则成为可复用、可组合、带上下文的类型安全谓词函数,并动态响应表单状态变化。

用闭包实现的柯里化函数,能天然支撑类型感知的表单校验引擎——它把“校验逻辑”和“数据类型”解耦,让每个验证规则既是可复用的谓词函数,又能按需注入上下文,最终形成语义清晰、类型安全、动态响应的校验体系。
把类型判断变成可组合的柯里化谓词
核心是将基础类型检查封装为纯函数,再用柯里化增强其灵活性:
-
先写类型断言函数:比如
function isString(x) { return typeof x === 'string'; }、function isArray(x) { return Array.isArray(x); } -
再用 curry 包一层:得到
const isString = curry(isString)。此时isString本身就是一个函数,可直接用于filter或map;传入值则立即返回布尔结果,如isString('abc')→true -
配合 Object.prototype.toString.call 做精准类型识别:例如
const isDate = curry(x => Object.prototype.toString.call(x) === '[object Date]'),避免typeof new Date()返回'object'的歧义
让校验规则携带运行时类型上下文
柯里化闭包能“记住”字段元数据,使同一验证函数在不同字段上表现不同:
- 定义一个通用邮箱校验工厂:
const createEmailValidator = curry((domainWhitelist, value) => { const domain = value.split('@').pop(); return domainWhitelist.includes(domain); }); - 绑定到具体字段:
validators: [createEmailValidator(['gmail.com', 'qq.com'])],这个闭包已捕获白名单,后续只接收用户输入值 - 同理,手机号校验可柯里化为
createPhoneValidator(countryCode),当表单中 country 字段变化时,重新生成新闭包,自动切换正则与长度规则
构建类型驱动的校验执行链
引擎遍历字段时,并非硬编码 if-else 判断类型,而是基于字段声明的 type 属性,动态匹配并调用对应柯里化验证器:
- 字段配置示例:
{ field: 'age', type: 'number', validators: [isRequired, isNumber, inRange(0, 120)] },其中inRange是柯里化函数,闭包保存了 min/max - 执行时,引擎自动识别
type: 'number',优先注入数值型预处理(如parseFloat),再交由isNumber等谓词校验,避免字符串'18'被误判为非法 - 错误消息也能类型化:若
isNumber('abc')失败,提示“请输入有效数字”;若isDate(new Date())成功但格式不合法,提示可进一步细化为“日期格式应为 YYYY-MM-DD”
与表单状态联动,实现真·类型感知
闭包的持久上下文能力,让校验器能响应表单整体状态变化,不只是单个字段值:
- 例如“密码确认”字段,其校验逻辑依赖“原始密码”字段当前值:
const matchPassword = curry((originalValue, confirmValue) => originalValue === confirmValue) - 在 validator 数组中,该闭包由表单状态实时生成:
matchPassword(formState.password),确保每次校验都基于最新输入 - 更进一步,当用户切换“账户类型”为“企业”时,引擎可批量重生成身份证号、税号等字段的验证闭包,自动启用
isUnifiedSocialCreditCode这类强类型校验器










