Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to get zod to read input as number and not text

I am trying to make an input that should take in a number between a certain range. When I submit it, zod says it expected a number but got a string.

import {z} from "zod"
import { fromZodError } from "zod-validation-error";

//give this file it's own unique name to identify the form it uses
export const creditCardData = z.object({
    //------name------
    firstName: z.string().min(3, 'Min Length must be 3').max(10, 'Max Length must be 10'),
    age: z.number().min(1).max(99).int()
})

export const defaultCardData={
    firstName:'',
    age: 0
}

export type CardData = z.infer<typeof creditCardData>

//form submit function
export const handleSubmit = (
event: React.FormEvent<HTMLFormElement>,
submission: CardData,
isError: (val: boolean) => void,
isLoading: (val: boolean) => void
) => {
    event.preventDefault();

    isLoading(true)
    const results = creditCardData.safeParse(submission);
    if (!results.success) {
        const errorType = fromZodError(results.error);
        console.log(errorType.message);
        isLoading(false)
        isError(true)

    } else {
    isError(false)
    isLoading(false)
    //put api call
    console.log(results.data);
}
};

Here is my zod file where I do my validation

import { useState } from "react";
import { CardData, defaultCardData, handleSubmit } from "./validation/zod";
import Input from "./components/Input";

function App() {
  //state date for form
  const [data, setData] = useState<CardData>(defaultCardData);
  //loading and function
  const [loading, setLoading] = useState(false);
  const isLoading = (val: boolean) => setLoading(val);
  //error and function
  const [error, setError] = useState(false);
  const isError = (val: boolean) => setError(val);

  return (
    <main className="min-h-screen flex justify-center flex-col items-center text-white">
      <h1 className="text-2xl font-bold ">Card Data</h1>

      <form
        className="text-black"
        onSubmit={(event) => handleSubmit(event, data, isError, isLoading)}
      >
        {/* //first name */}
        <Input
          label="First Name "
          id="firstName"
          value={data.firstName}
          handleChange={(e: { target: { value: string } }) => {
            setData({ ...data, firstName: e.target.value });
          }}
        />
        {/* //age */}
        <Input
          label="Age "
          id="age"
          value={data.age}
          type="number"
          handleChange={(e: { target: { value: number } }) => {
            setData({ ...data, age: e.target.value });
          }}
        />
        {/* //submit */}
        <button
          className="block mt-4 p-2 bg-white border-black border-2 rounded-md"
          type="submit"
        >
          Submit
        </button>
        {loading && <p>Loading...</p>}
        {error && <p>Error on submission</p>}
      </form>
    </main>
  );
}

export default App;

and here is the part where I have the user input. When I submit I get the error "Validation error: Expected number, received string at "age". "

like image 482
Zach philipp Avatar asked Nov 30 '25 15:11

Zach philipp


1 Answers

As per the Zod documentation, Zod now provides a more convenient way to coerce primitive values.

age: z.coerce.number().gte(18, 'Must be 18 and above');
like image 54
Zxeenu Avatar answered Dec 03 '25 11:12

Zxeenu



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!