Typescript表单验证策略模式

443 阅读1分钟

目标:在表单验证场景,对策略模式的一次实践

代码

基于Typescript,对于password这类需要验证长度范围的输入进行单独处理,将额外的判定条件利用strategyContext辅助方法进行转换,最终得到类型为(password: string) => boolean的函数体,保存在Validation类中的rules数组中。

// 验证密码的长度
type ValidPassword = {
  minLength: number;
  maxLength: number;
};

// 验证内容
interface ValidStrategyProps {
  isValidPhone: (phone: string) => boolean;
  isValidPassword: (password: string) => boolean;
}

// 验证方法
export const ValidStrategy = {
  isValidPhone: (phone: string): boolean => /1\d{10}/.test(`${phone}`),
  isValidPassword: (password: string): ((extra?: ValidPassword) => boolean) =>
    (extra: ValidPassword = { minLength: 8, maxLength: 20 }) =>
      password.length >= extra.minLength && password.length <= extra.maxLength,
};

// 将用户输入转化为函数形式,存放在Validation-rules中
const strategyContext = (rule: keyof ValidStrategyProps, toValidEle: string, extra?: ValidPassword):
(() => boolean) => {
  if (rule === 'isValidPassword') {
    const fn = ValidStrategy[rule](toValidEle);
    return () => fn(extra);
  }
  return () => ValidStrategy[rule](toValidEle);
};

// 验证类,保存验证方法
export default class Validation {
  rules: (() => boolean)[];

  constructor() {
    this.rules = [];
  }

  add(rule: keyof ValidStrategyProps, toValidEle: string): void {
    this.rules.push(strategyContext(rule, toValidEle));
  }

  valid(): boolean {
    return this.rules.every(rule => rule());
  }
}

使用

const validationIns = new Validation();
validationIns.add('isValidPhone', 1234567890);
validationIns.add('isValidPassword', 010101010101);
const isValid = validationIns.valid();