Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to allow `null` as default value in Yup schema, while still not allowing `null` to be submitted?

I have this Yup-schema defined:

export const ExpectedIncomeSchema = object({
  newIncome: number()
    .required()
    .typeError()
    .min(0)
    .integer(),
  fromDate: date()
    .required()
    .typeError()
    .min(startOfToday()),
});

export type ExpectedIncomeValues = Asserts<typeof ExpectedIncomeSchema>;

I'm now trying to use this schema for validation in a react-hook-form, and ran into the issue that I'm not allowed to set the defaultValues to null or "". Kind of obvious, since Typescript says the only allowed types here are number and Date, but I don't want to default these values to a valid value like 0 or some randomly picked date. I want these fields to be initially empty.

const methods = useForm<ExpectedIncomeValues>({
  resolver: yupResolver(ExpectedIncomeSchema),
  defaultValues: {
    newIncome: null, // <-- only number allowed, so type error in both Typescript and validation
    fromDate: null, // <-- only Date allowed, so type error in both Typescript and validation
  },
);

How can make both Yup and Typescript happy here? I want the fields to be nullable when I setup the form, but not when after the schema has been validated.

Does Yup have something clever for this, or do I have to do something hacky like this?

export type Nullable<T> = {
  [P in keyof T]: T[P] | null;
};


export type ExpectedIncomeFormValues = Nullable<ExpectedIncomeValues>;

One issue with this though, is that the error message will be a "type error" message, not the "required" message that I'd want in this case. 😕

like image 664
Svish Avatar asked Oct 27 '25 09:10

Svish


1 Answers

The following seems to work, but not sure if it's actually correct. I realized yup has two type-helpers, TypeOf and Asserts. By adding .nullable(true) to the schema, the first will allow null, while the second will not. Which is what I want. 👍

const schema = object({
  newIncome: number()
    .required()
    .nullable(true)
    .min(0)
    .integer(),
  fromDate: date()
    .required()
    .nullable(true)
    .min(startOfToday()),
});


type ValuesWithNull =
  TypeOf<typeof ExpectedIncomeSchema>;

type ValuesWithoutNull =
  Asserts<typeof ExpectedIncomeSchema>;

like image 137
Svish Avatar answered Oct 28 '25 22:10

Svish



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!