スキーマライブラリの共通インターフェイスを提供するstandard-schema v1をご紹介
standard-schemaのv1がリリースされたので触ってみた。
standard-schema とは
現在バリデーションライブラリとしてzodや valibot、arktypeなどがありますが、それらをTanStack Formなどの別ライブラリと統合して使用する際には専用のadapterを使用する必要がありました。以下のコードはTanStack Formとzodを組み合わせた時の例です。
import { useForm } from "@tanstack/react-form";
// zod用のadapterをインストールする必要がある
import { zodValidator } from "@tanstack/zod-form-adapter";
import { z } from "zod";
const userSchema = z.object({
name: z.string(),
});
export function Form() {
const form = useForm({
defaultValues: {
name: "",
},
// zodValidatorをセットする
validatorAdapter: zodValidator(),
validators: {
onChange: userSchema,
},
onSubmit: (values) => {
console.log(values);
},
});
return (
<form onSubmit={form.handleSubmit}>
<form.Field
name="name"
children={(field) => (
<div>
<label htmlFor={field.name}>Name:</label>
<input
id={field.name}
name={field.name}
value={field.state.value}
onBlur={field.handleBlur}
onChange={(e) => field.handleChange(e.target.value)}
/>
</div>
)}
/>
<button type="submit">Submit</button>
</form>
);
}
また、TanStack Formではこのadapterがzod、yup、valibotのものしかなく、それ以外のバリデーションライブラリと組み合わせることはできませんでした(後述しますが、最新のTanStack Formはstandard-schemaを受け入れているため、他のライブラリも使えます)。
しかしなぜ、各バリデーションライブラリ専用のadapterが必要なのでしょうか。それは各ライブラリごとにinterfaceが違うからです。そこで登場したのがstandard-schemaです。
standard-schemaはバリデーションライブラリの共通インターフェースを定義し、その定義に沿って各バリデーションライブラリが実装することにより、ライブラリに互換性を持たせ、1つのadapterでさまざまなバリデーションライブラリを使用できるようにすることを目的としています。
standard-schemaの使い方
READMEにも書かれているシンプルな使い方を紹介します。まず、standardValidateという関数を定義します。
次にstandard-schemaのインターフェースを実装しているライブラリでスキーマを定義します。
そして、standardValidateとスキーマを組み合わせ、以下のonSubmit関数の中で行なっているようにバリデーションを実行することができます。
standardValidateの第2引数にはstandard-schemaのインターフェースを実装しているライブラリであれば、どのライブラリでも使用できるため、ライブラリの差し替えが容易になります。
各ライブラリの対応
standard-schemaを実装しているバリデーションライブラリと、standard-schemaをサポートしているライブラリは以下に記載されています。
TanStack Form
初めの方でTanStack Formとzodの組み合わせの例を紹介しましたが、TanStack Formもstandard-schemaをサポートしており、現在の最新のバージョンでは@tanstack/zod-form-adapter
のようなライブラリを使用する必要はなくなりました。また、組み合わせることのできるバリデーションライブラリもstandard-schemaを実装しているバリデーションライブラリであれば自由に選べるようになりました。
以下がstandard-schemaを利用したときの例です。差分としては@tanstack/zod-form-adapter
を削除しただけです。
import { useForm } from "@tanstack/react-form";
- // zod用のadapterをインストールする必要がある
- import { zodValidator } from "@tanstack/zod-form-adapter";
import { z } from "zod";
const userSchema = z.object({
name: z.string(),
});
export function Form() {
const form = useForm({
defaultValues: {
name: "",
},
- // zodValidatorをセットする
- validatorAdapter: zodValidator(),
validators: {
onChange: userSchema,
},
onSubmit: (values) => {
console.log(values);
},
});
return (
<form onSubmit={form.handleSubmit}>
<form.Field
name="name"
children={(field) => (
<div>
<label htmlFor={field.name}>Name:</label>
<input
id={field.name}
name={field.name}
value={field.state.value}
onBlur={field.handleBlur}
onChange={(e) => field.handleChange(e.target.value)}
/>
</div>
)}
/>
<button type="submit">Submit</button>
</form>
);
}
これにより、standard-schemaをサポートする前のTanStack Formではzod、valibot、yupしか選べませんでしたが、サポート後はArkType、Arri Schema、TypeMapも使えるようになりました。今後もstandard-schemaを実装するバリデーションライブラリが増えれば、さらに色々なバリデーションライブラリを使えるようになるでしょう。
まとめ
standard-schemaの登場により、adapterのようなglueなライブラリが必要なくなり、ライブラリの組み合わせの自由度が増しました。今後、standard-schemaを実装/サポートするライブラリが増えることでバリデーションライブラリの乗り換えなども楽になりそうだなと思っており、楽しみです。
Discussion