- JavaScript/TypeScriptベースのスキーマライブラリが共通インターフェースを実装するよう設計された仕様
- ライブラリごとにユーザー定義の型検証ロジックを再利用できるようにし、ツール同士が個別のアダプターなしで相互運用できるようにするのが目的
- Zod、Valibot、ArkType など主要ライブラリの作者が共同で設計
主要インターフェース (StandardSchemaV1)
~standard というオブジェクトプロパティを通じて、すべての仕様を実装
~standard の中に version、vendor、validate、types などの必須プロパティが存在
validate 関数は成功時に value を、失敗時に issues 配列を返す
types プロパティにより、TypeScriptでスキーマの入力 (input) と出力 (output) の型を推論できる
- すべてのアップデートは、メジャーバージョン変更でない限り互換性を維持
設計目標
- ランタイム検証のサポート: 標準方式でエラー情報を標準化して渡す
- 静的型推論のサポート: TypeScriptベースのライブラリが推論した型情報を明示的に公開
- 簡潔さ: 既存ライブラリ関数に数行追加するだけで実装可能
- API衝突の回避:
~standard という1つの名前空間にすべてを入れ、既存APIと衝突しないようにする
- 開発者体験の維持:
~standard のようにチルダ (~) で始め、補完での優先順位を下げる
どのライブラリが実装しているか
- すでに Zod、Valibot、ArkType、Arri Schema、TypeMap などで Standard Schema をサポート
- tRPC、TanStack Form、TanStack Router、Hono Middleware なども Standard Schema をベースにユーザースキーマを受け入れている
自分のライブラリに仕様を実装する方法
StandardSchemaV1 インターフェースをライブラリにコピーし、~standard プロパティを追加する
validate 関数を既存の検証関数に接続し、成功時は { value }、失敗時は { issues } を返すようにする
- 必要に応じて非同期検証も可能だが、同期検証を推奨
Standard Schema でユーザー定義スキーマを受け取る方法
- スキーマライブラリなしで直接使うには、
@standard-schema/spec をインストールするか、インターフェースをコピーして使う
- 例の関数
standardValidate のように、標準インターフェースを持つスキーマであれば、どのライブラリでも同じ方法でバリデーション可能
- 同期検証だけを許可する場合は、
validate の返り値が Promise かどうかを確認してから例外処理を行えばよい
FAQ
@standard-schema/spec の依存関係を追加する必要はあるか?: 必ずしも依存関係として追加する必要はなく、コピーして使用できる
- dev dependency としては追加不可: ライブラリのパブリックAPIになるため、実際の配布環境でも利用可能である必要がある
~standard の前にチルダ (~) を使った理由: 補完で他のプロパティより後ろに表示されるよう意図している
- Symbol ではなく文字列キーを使った理由: TypeScriptでSymbolキーを使うと、補完順や型推論で問題が起きるため
まだコメントはありません。