Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

スキーマ

なぜスキーマが必要か

generate() はスキーマなしでも動作します。では、なぜスキーマを定義するのでしょうか?

1. 型変換 — 入力値を正しい型に

入力データは文字列や数値が混在していることがあります。スキーマで型を指定すれば、出力 JSON の型を保証できます。

// スキーマなし: age が文字列 "25" のまま
{ name: 'Taro', age: '25' }

// asNumber() を使用: age が数値 25 に変換
{ name: 'Taro', age: 25 }

2. フィルタリング — 不要な列を自動除外

スキーマは許可リストとして機能します。定義されたパスのみが出力に含まれ、それ以外は自動的に除外されます。入力データの余分な列が、API のレスポンスを汚染する心配がありません。

// 入力データに「備考」「担当者」列があっても、スキーマに定義がなければ除外される
const schema = defineSchema({
  customer: {
    name: asString(),
    email: asString(),
    // ← 「備考」「担当者」はここに定義がないため出力から除外
  },
})

キャスト関数

各フィールドの型変換を定義する組み込み関数です。

関数変換内容入力例出力例
asString()String(value)123"123"
asNumber()Number(value)"42"42
asBoolean()Boolean(value)"true"true
asDate()new Date(value)"2024-01-15"Date オブジェクト
asCustom(fn)カスタム関数任意任意
import { defineSchema, asString, asNumber, asBoolean, asDate, asCustom } from 'path-binder'

const schema = defineSchema({
  user: {
    name: asString(),
    age: asNumber(),
    active: asBoolean(),
    joinedAt: asDate(),
    score: asCustom((v) => Math.round(Number(v))),
  },
})

配列スキーマ

配列の各要素に対するスキーマを arrayOf() で定義します。

import { defineSchema, asString, asNumber, arrayOf } from 'path-binder'

const schema = defineSchema({
  user: {
    name: asString(),
    // プリミティブ値の配列
    tags: arrayOf(asString()),
    // オブジェクト配列
    contacts: arrayOf({
      type: asString(),
      value: asString(),
    }),
  },
})

ルーズスキーマ(asAny)

いつ使う: プロトタイプ段階で全列を通したい場合や、一部だけ型変換したい場合

import { defineSchema, asAny, asNumber } from 'path-binder'

// 全パスをキャストなしで通す
const looseSchema = defineSchema({
  user: asAny(),
})

// 全パスを通すが、age だけは数値にキャスト
const partialSchema = defineSchema({
  user: asAny({
    age: asNumber(),
  }),
})

asAny() はフィルタリングを無効にします。スキーマに定義されていないパスも出力に含まれます。


カスタムキャスト

asCustom() で任意の変換ロジックを定義します。

カンマ区切りタグの分割

const schema = defineSchema({
  product: {
    tags: asCustom((v) => String(v).split(',').map((t) => t.trim())),
    // "食品,冷凍,セール" → ["食品", "冷凍", "セール"]
  },
})

例外スロー時の動作

キャスト関数内で例外がスローされた場合、そのエントリはスキップされます。

const schema = defineSchema({
  config: {
    priority: asCustom((v) => {
      const n = Number(v)
      if (Number.isNaN(n)) {
        throw new Error('Invalid number')
      }
      return n
    }),
  },
})

スキーマあり vs なしの比較

項目スキーマなしスキーマあり
型変換なし(元の値のまま)キャスト関数で制御
不要列の除外されない(全パスが出力)許可リストとして機能
例外時のスキップなしキャスト関数が例外をスローした場合、エントリをスキップ
開発速度速い(定義不要)やや遅い(定義が必要)
本番利用非推奨推奨

次のステップ: スキップ処理でエラーハンドリングを設定する