📑

Zodを使ってバリデーションするときに文字列→数値変換を挟む

2022/06/23に公開1

preprocessが使える

https://zod.dev/?id=preprocess

schema.ts
export const formSchema = z.object(
  {
    quantity: z.preprocess(
      (v) => Number(v),
      z
        .number({ required_error: ValidationMsg.REQUIRED })
        .min(4, ValidationMsg.Number.MIN(4))
    ),
  }
);
expost type Form = z.infer<typeof formSchema>

preprocessメソッドを使うと第一引数で事前にしたい処理を渡すことができ、第二引数でスキーマを渡せる。
useFormと合わせて使ってみたところ、変換後の第2引数のスキーマでバリデーションできることが確認できた。

sample.tsx
const Sample = () => {
  const {
    register,
    handleSubmit,
    formState: { errors },
    setValue,
    getValues,
  } = useForm<Form>({
    resolver: zodResolver(formSchema),
  });
  return(
    <>
    <TextField
      type="number"
      required
      label={FormLabel.MAX}
      fullWidth
      {...register("quantity")}
      error={"quantity" in errors}
      helperText={errors.quantity?.message}
    />
    </>
  );
}

Discussion

さかもとさかもと

いまだとショートハンド的な coerce というのが提供されているようですね。

ちょっとだけ短くかける。

export const formSchema = z.object(
-  {
-    quantity: z.preprocess(
-      (v) => Number(v),
-      z
-        .number({ required_error: ValidationMsg.REQUIRED })
-        .min(4, ValidationMsg.Number.MIN(4))
-    ),
-  },
+  {
+    quantity: z.coerce
+        .number({ required_error: ValidationMsg.REQUIRED })
+        .min(4, ValidationMsg.Number.MIN(4))
+    ),
+  },

参考