[TypeScript]LoginForm中でのValidationDesign

<h2>Validation</h2>
uiの核心的な要求事項は、それぞれの入力フィールドの値が入力された時、 
この値が正常によく入力された値であるかを確認する部分がなければならない。
これを実現する際、2つ程度の悩みにならなければならない。
<br>
1つ目は、それぞれのケイソンつまり、Validationルール。
これらのルールをどう表現するかということです。。
もちろんコードでifを使って作成することもできるが、かなり非効率的。
<br><br>
２つ目は、一つの入力フィールドに様々なvalidationルールが適用されなければならないということです。
各入力フィールドにそれぞれのベリデーションルールではなく、1つの入力フィールドに適用する必要がある 
validationルールといえば、これをどのように処理するのが効果的な方法なのか考えなければならない。

<h2>正規式とは</h2>
ReqExp はRegular Expression という正規式、JavascriptObjectである。
正規式は特殊な目的で特化したプログラミング言語です。<br>
JavaScriptのようなプログラミング言語は汎用的なプログラミング言語であり、様々なことができるようにデザインされています。それでどんなアプリケーションも全て作り出すことができる反面、逆に特定目的の仕事は非常に非効率的にせざるを得ない側面があります。<br>
代表的に文字列から何かを探し出すこと（大文字があるのか小文字があるのか数字があるのか…）をジャバスクリプトコードだけで作成することは難しい。 そのため、このようなものに特化した一種のパターンマッチングに特化した言語を正規式という。

<h2>Validationルール</h2>

```typescript:constants.ts
export type AnyObject = {
  [key: string]: any;
}

export type ValidateRule = {
  rule: RegExp;
  match: boolean;
  message: string;
}
```

```typescript:common.ts
import { ValidateRule } from "./types";

export const RequireRule: ValidateRule = {
  rule: /.+/,
  match: true,
  message: '必須入力項目です.',
};

export const CantContainWhitespace: ValidateRule = {
  rule: /\s/,
  match: false,
  message: '空白は含められません.',
};

export const CantStartNumber: ValidateRule = {
  rule: /^\d/,
  match: false,
  message: '数字で始まるIDは使用できません.',
}


export const MinimumLengthLimit = (limit: number): ValidateRule => ({
  rule: new RegExp(`(.){${limit}}`),
  match: true,
  message: `少なくとも${limit}文字以上でなければなりません.`,
});
```

正規式表現において2つの方法があります。
1つ目は 「//」 リテラルで表現する方法
二つ目はRegExp提供される関数を利用して表現する方法です。Minimum Length Limit()は表現される正規式の中に毎回変わる数字値を広くしなければならないが、リテラールにすると数字値を固定で入れなければならないです。 
しかし、実際に使用する際にはどのような値を使うか全く分からないため、ReqExp関数を利用すれば正規式が作成できます。

<h2>一つの入力フィールドに様々なvalidationルールの適用</h2>
一つのフィールドにn個のValidate Ruleが付いている場合はどう処理するか？

```typescript:app.ts
private initialize = () => {
    const nameField = new TextField('#required-fields', { 
      id: 'name', label: '名前', type: 'text', placeholder: '名前を入力してください', require: true,
    });

    const idField = new TextField('#required-fields', { 
      id: 'id', label: 'ID', type: 'text', placeholder: 'IDを入力してください', require: true,
    });

    const emailField = new TextField('#required-fields', { 
      id: 'email', label: 'e-mail', type: 'email', placeholder: 'e-mailを入力してください', require: true,
    });
    
    const passwordField = new PasswordField('#required-fields', { 
      id: 'password', label: 'パスワード', placeholder: 'パスワードを入力してください', 
    });

    const addressField = new AddressField('#optional-fields', {
      id: 'address', label: 'お届け先住所',
    });

    idField.addValidateRule(CantContainWhitespace);
    idField.addValidateRule(CantStartNumber);
    idField.addValidateRule(MinimumLengthLimit(3));

    emailField.addValidateRule(CantContainWhitespace);

    this.fields.push(nameField);
    this.fields.push(idField);
    this.fields.push(emailField);
    this.fields.push(passwordField);
    this.fields.push(addressField);
  }

  public render = () => {
    this.container.innerHTML = this.template(this.data);
    this.fields.forEach(field => {
      field.render(true);
    });

    this.container.addEventListener('submit', this.onSubmit);
  }
```
それぞれのフィールドらはaddValidateRuleというメソッドを提供するようデザインされています。
TextFiledは名前、ID、Eメールという形で使われます。
当然validationの方法は異なります。 
しかし、そのvalidation方法はTextFieldが自ら規定することはできません。 どんな用途で使われるようになるかTextFieldは分からないから！
その用途を指定する側から、validationルールも指定してもらうしかありません。 そのため、TextFieldクラスはどのようなvalidationルールになるか分かりませんが、少なくともn個を処理できる機能はサポートしなければならないとデザインできます。