I'm using material ui components with react-hook-form and zod validation. I have a bloodType
select field:
const bloodTypes = [ "A+", "A-", "B+", "B-", "AB+", "AB-", "O+", "O-" ] as const;
const schema = z.object({
bloodType: z.enum(bloodTypes),
});
type FormType = z.infer<typeof schema>;
The problem comes in the mui component in the defaultValue
prop. Since this is a controlled component I need to give it a defaultValue
but Typescript complains that the ""
value is not assignable to the bloodType
type.
<FormControl fullWidth error={!!errors.bloodType} margin="normal">
<InputLabel id="bloodtype-label">Tipo de sangre</InputLabel>
<Controller
name="bloodType"
defaultValue="" // <-------- HERE
control={control}
render={({ field }) => (
<Select
{...field}
labelId="bloodtype-label"
label="Tipo de sangre"
>
{bloodTypes.map((bloodtype) => (
<MenuItem key={bloodtype} value={bloodtype}>
{bloodtype}
</MenuItem>
))}
</Select>
)}
/>
<FormHelperText>{errors.bloodType?.message}</FormHelperText>
</FormControl>
That makes sense since bloodType
only allows the values defined in the schema, but I would like the initial value to be empty.
I tried setting the defaultValue to undefined
but then MUI throws an alert MUI: You have provided an out-of-range value 'undefined' for the select
.
So my question is how can I allow an empty string as defaultValue but reject on zod validation and maintain correct types?
As a workaround I'm using .refine
to check if the value is ""
and return false so it fails the validation, but I feel that it is not the correct approach.