柯里化实现多步骤表单校验的核心是解耦校验规则与待校验数据,使每步仅关注当前字段并累积结果;它提升可复用性、可组合性、可中断性和可调试性。

用柯里化实现多步骤表单校验,核心是把“校验规则”和“待校验数据”解耦,让每一步只关心当前字段,同时保留前序结果、累积错误或有效值。它不是为了炫技,而是让校验逻辑更可复用、易组合、可中断、易调试。
柯里化校验函数的基本结构
一个典型的校验函数接受字段名、规则(如非空、邮箱格式、最小长度)和值,返回 { valid: boolean, error?: string, value?: any }。柯里化后,先固定规则和字段名,生成一个只等输入值的函数:
const required = (field) => (value) =>
value != null && value !== ''
? { valid: true, value }
: { valid: false, error: `${field} 是必填项` };
const email = (field) => (value) =>
/^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(value)
? { valid: true, value }
: { valid: false, error: `${field} 格式不正确` };
// 使用:生成具体校验器
const checkName = required('姓名');
const checkEmail = email('邮箱');
组合多步校验:用 reduce 累积结果
每步校验都接收上一步的输出(如已校验的字段对象),再加入当前字段结果。用柯里化 + 函数组合,可写出声明式流程:
// 柯里化组合器:(prevResult, nextValidator) => newResult
const step = (validator) => (prev) => {
const res = validator(prev.value?.[validator.field] ?? prev.input);
if (!res.valid) return { ...prev, valid: false, errors: [...prev.errors, res.error] };
return {
...prev,
valid: true,
value: { ...prev.value, [validator.field]: res.value },
errors: prev.errors
};
};
// 定义各步校验器(已柯里化)
const validateStep1 = step(required('用户名'));
const validateStep2 = step(email('邮箱'));
const validateStep3 = step((val) => val.length >= 6
? { valid: true, value: val }
: { valid: false, error: '密码至少6位' });
// 执行三步校验(按顺序调用)
const result = [validateStep1, validateStep2, validateStep3].reduce(
(acc, fn) => fn(acc),
{ input: '', value: {}, errors: [], valid: true }
);
适配真实表单:支持异步校验与中断
实际中,某些校验可能需发请求(如用户名是否已存在)。柯里化可自然融入 Promise:
立即学习“Java免费学习笔记(深入)”;
const uniqueUsername = (field) => async (value) => {
const res = await fetch(`/api/check?user=${value}`);
const data = await res.json();
return data.available
? { valid: true, value }
: { valid: false, error: `${field} 已被占用` };
};
// 柯里化异步校验器仍保持统一签名
const checkUnique = uniqueUsername('用户名');
// 在步骤中处理 Promise(需用 async reduce 或 for...of)
const runSteps = async (steps, initial) => {
let acc = initial;
for (const step of steps) {
acc = await step(acc);
if (!acc.valid) break; // 失败即中断,不继续后续校验
}
return acc;
};
封装成 Hook 或工具类提升复用性
在 React 中可封装为自定义 Hook,把柯里化校验器、当前步骤、错误状态封装起来:
function useFormValidation(validators) {
const [state, setState] = useState({ value: {}, errors: [], valid: true });
const validateStep = useCallback((stepIndex, formData) => {
const validator = validators[stepIndex];
if (!validator) return;
const res = validator(formData);
setState(prev => ({
...prev,
...res,
value: { ...prev.value, ...res.value }
}));
}, [validators]);
return { ...state, validateStep };
}
// 使用时只需传入已柯里化的校验器数组
const validators = [
required('手机号'),
(val) => /^1[3-9]\d{9}$/.test(val)
? { valid: true, value: val }
: { valid: false, error: '手机号格式错误' },
required('验证码')
];


















