SCALE — Build Lab
開発パターン · TYPESCRIPT PATTERN

バリデーションヘルパ集

CATEGORY開発パターン TYPETypeScript Pattern EFFORT30〜60分 DIFFICULTY
PRIMARY CODE
ts
type ValidResult = { ok: true } | { ok: false; msg: string };

export const v = {
  required: (val: any): ValidResult =>
    (val == null || val === '') ? { ok: false, msg: '必須項目です' } : { ok: true },

  email: (val: string): ValidResult =>
    /^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(val) ? { ok: true } : { ok: false, msg: 'メールアドレス形式が不正です' },

  url: (val: string): ValidResult => {
    try { new URL(val); return { ok: true }; }
    catch { return { ok: false, msg: 'URL形式が不正です' }; }
  },

  phone: (val: string): ValidResult =>
    /^[\d\-+()\s]{10,}$/.test(val) ? { ok: true } : { ok: false, msg: '電話番号の桁が不足しています' },

  minLength: (n: number) => (val: string): ValidResult =>
    val.length >= n ? { ok: true } : { ok: false, msg: `${n}文字以上で入力してください` },

  maxLength: (n: number) => (val: string): ValidResult =>
    val.length <= n ? { ok: true } : { ok: false, msg: `${n}文字以内で入力してください` },

  pattern: (re: RegExp, msg = '形式が不正です') => (val: string): ValidResult =>
    re.test(val) ? { ok: true } : { ok: false, msg },

  // チェーン: 複数バリデータを順に評価
  all: (...validators: Array<(v: any) => ValidResult>) => (val: any): ValidResult => {
    for (const fn of validators) {
      const r = fn(val);
      if (!r.ok) return r;
    }
    return { ok: true };
  },
};

// 使い方:
// const r = v.all(v.required, v.email)('user@example.com');
// if (!r.ok) alert(r.msg);
前提条件
Tailwind CSS v4TypeScript 5
USE CASES
  • 任意のダッシュボードに組み込み

バリデーションヘルパ集

:LiTarget: 用途

Email・URL・電話・必須・長さ・パターン等の汎用バリデーション。zod 不要の軽量版。

:LiSparkle: 特徴

  • 一通り揃ったvalidator
  • メッセージ日本語
  • 型推論
  • チェーン可

:LiCode: コード(コピペ用)

type ValidResult = { ok: true } | { ok: false; msg: string };

export const v = {
  required: (val: any): ValidResult =>
    (val == null || val === '') ? { ok: false, msg: '必須項目です' } : { ok: true },

  email: (val: string): ValidResult =>
    /^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(val) ? { ok: true } : { ok: false, msg: 'メールアドレス形式が不正です' },

  url: (val: string): ValidResult => {
    try { new URL(val); return { ok: true }; }
    catch { return { ok: false, msg: 'URL形式が不正です' }; }
  },

  phone: (val: string): ValidResult =>
    /^[\d\-+()\s]{10,}$/.test(val) ? { ok: true } : { ok: false, msg: '電話番号の桁が不足しています' },

  minLength: (n: number) => (val: string): ValidResult =>
    val.length >= n ? { ok: true } : { ok: false, msg: `${n}文字以上で入力してください` },

  maxLength: (n: number) => (val: string): ValidResult =>
    val.length <= n ? { ok: true } : { ok: false, msg: `${n}文字以内で入力してください` },

  pattern: (re: RegExp, msg = '形式が不正です') => (val: string): ValidResult =>
    re.test(val) ? { ok: true } : { ok: false, msg },

  // チェーン: 複数バリデータを順に評価
  all: (...validators: Array<(v: any) => ValidResult>) => (val: any): ValidResult => {
    for (const fn of validators) {
      const r = fn(val);
      if (!r.ok) return r;
    }
    return { ok: true };
  },
};

// 使い方:
// const r = v.all(v.required, v.email)('user@example.com');
// if (!r.ok) alert(r.msg);

:LiHandPointer: 使い方

対象プロジェクトに該当ファイルをコピーして、props を流し込むだけ。

:LiAlertCircle: 注意事項

  • 依存パッケージを忘れず追加