I am using react-hook-form with zod schema validation, and I am trying to get the name, taxId, companyName, taxOffice, and billingAddress fields to show up in the errors object. These fields are part of a discriminatedUnion in my schema, but when I try to access errors.name, I get the error:
Property 'name' does not exist on type 'FieldErrors<{ phone: string; email: string; city: string; district: string; address: string; paymentMethod: "paypal" | "bank"; customerType: "individual"; name: string; code?: string | undefined; notes?: string | undefined; } | { ...; }>'.
Property 'name' does not exist on type 'Partial<FieldErrorsImpl<{ phone: string; email: string; city: string; district: string; address: string; paymentMethod: NonNullable<"paypal" | "bank">; customerType: "corporate"; taxId: string; ... 4 more ...; notes: string; }>> & { ...; }'.ts(2339)
Code Snippet:
const commonSchema = z.object({
phone: z
.string()
.regex(/^\+?[1-9]\d{1,14}$/, "Geçerli bir telefon numarası giriniz")
.nonempty("Telefon zorunludur"),
email: z
.string()
.email("Geçerli bir email giriniz")
.nonempty("Email zorunludur"),
city: z.string().nonempty("Lütfen il seçiniz"),
district: z.string().nonempty("Lütfen ilçe seçiniz"),
address: z.string().nonempty("Adres zorunludur"),
paymentMethod: z.enum(["paypal", "bank"]),
code: z.string().optional(),
notes: z.string().optional(),
});
const individualSchema = z.object({
customerType: z.literal("individual"),
name: z.string().nonempty("Ad Soyad zorunludur"),
});
const corporateSchema = z.object({
customerType: z.literal("corporate"),
taxId: z.string().nonempty("Vergi Numarası zorunludur"),
companyName: z.string().nonempty("Şirket Adı zorunludur"),
taxOffice: z.string().nonempty("Vergi Dairesi zorunludur"),
billingAddress: z.string().nonempty("Fatura Adresi zorunludur"),
});
const schema = z
.discriminatedUnion("customerType", [individualSchema, corporateSchema])
.and(commonSchema);
export type PaymentForm = z.infer<typeof schema>;
export default function PaymentForm() {
const {
control,
handleSubmit,
watch,
formState: { errors },
} = useForm<PaymentForm>({
resolver: zodResolver(schema),
defaultValues: {
customerType: "individual",
paymentMethod: "paypal",
},
});
const customerType = watch("customerType");
return (
<>
{customerType === "individual" && (
<Controller
name="name"
control={control}
render={({ field }) => (
<TextField
{...field}
label="Ad Soyad*"
variant="outlined"
fullWidth
error={!!errors.name} // Property 'name' does not exist on type 'FieldErrors<{ phone: string; email: string...
helperText={errors.name?.message || " "} // Property 'name' does not exist on type 'FieldErrors<...
/>
)}
/>
)}
</>
);
}
Image:
Issue:
The fields from commonSchema, such as phone, work fine in errors. However, fields inside the discriminatedUnion (like name, taxId, companyName, taxOffice, billingAddress) are not being recognized in the errors object. When I type errors. in TypeScript, I get intellisense for other fields, but name is missing. I get the error: Property 'name' does not exist on type 'FieldErrors<...>'.
Expected Behavior:
I expect name, taxId, companyName, taxOffice, and billingAddress to show up in errors when invalid, and I also expect to be able to access them with intellisense.
I am using react-hook-form with zod schema validation, and I am trying to get the name, taxId, companyName, taxOffice, and billingAddress fields to show up in the errors object. These fields are part of a discriminatedUnion in my schema, but when I try to access errors.name, I get the error:
Property 'name' does not exist on type 'FieldErrors<{ phone: string; email: string; city: string; district: string; address: string; paymentMethod: "paypal" | "bank"; customerType: "individual"; name: string; code?: string | undefined; notes?: string | undefined; } | { ...; }>'.
Property 'name' does not exist on type 'Partial<FieldErrorsImpl<{ phone: string; email: string; city: string; district: string; address: string; paymentMethod: NonNullable<"paypal" | "bank">; customerType: "corporate"; taxId: string; ... 4 more ...; notes: string; }>> & { ...; }'.ts(2339)
Code Snippet:
const commonSchema = z.object({
phone: z
.string()
.regex(/^\+?[1-9]\d{1,14}$/, "Geçerli bir telefon numarası giriniz")
.nonempty("Telefon zorunludur"),
email: z
.string()
.email("Geçerli bir email giriniz")
.nonempty("Email zorunludur"),
city: z.string().nonempty("Lütfen il seçiniz"),
district: z.string().nonempty("Lütfen ilçe seçiniz"),
address: z.string().nonempty("Adres zorunludur"),
paymentMethod: z.enum(["paypal", "bank"]),
code: z.string().optional(),
notes: z.string().optional(),
});
const individualSchema = z.object({
customerType: z.literal("individual"),
name: z.string().nonempty("Ad Soyad zorunludur"),
});
const corporateSchema = z.object({
customerType: z.literal("corporate"),
taxId: z.string().nonempty("Vergi Numarası zorunludur"),
companyName: z.string().nonempty("Şirket Adı zorunludur"),
taxOffice: z.string().nonempty("Vergi Dairesi zorunludur"),
billingAddress: z.string().nonempty("Fatura Adresi zorunludur"),
});
const schema = z
.discriminatedUnion("customerType", [individualSchema, corporateSchema])
.and(commonSchema);
export type PaymentForm = z.infer<typeof schema>;
export default function PaymentForm() {
const {
control,
handleSubmit,
watch,
formState: { errors },
} = useForm<PaymentForm>({
resolver: zodResolver(schema),
defaultValues: {
customerType: "individual",
paymentMethod: "paypal",
},
});
const customerType = watch("customerType");
return (
<>
{customerType === "individual" && (
<Controller
name="name"
control={control}
render={({ field }) => (
<TextField
{...field}
label="Ad Soyad*"
variant="outlined"
fullWidth
error={!!errors.name} // Property 'name' does not exist on type 'FieldErrors<{ phone: string; email: string...
helperText={errors.name?.message || " "} // Property 'name' does not exist on type 'FieldErrors<...
/>
)}
/>
)}
</>
);
}
Image:
Issue:
The fields from commonSchema, such as phone, work fine in errors. However, fields inside the discriminatedUnion (like name, taxId, companyName, taxOffice, billingAddress) are not being recognized in the errors object. When I type errors. in TypeScript, I get intellisense for other fields, but name is missing. I get the error: Property 'name' does not exist on type 'FieldErrors<...>'.
Expected Behavior:
I expect name, taxId, companyName, taxOffice, and billingAddress to show up in errors when invalid, and I also expect to be able to access them with intellisense.
Share Improve this question asked Mar 26 at 5:29 LibrouseLibrouse 491 silver badge5 bronze badges1 Answer
Reset to default 0You have to casting the errors
with FieldErrors
of individualSchema
type.
{customerType === 'individual' && (
<Controller
name="name"
control={control}
render={({ field }) => {
const individualSchErrors = errors as FieldErrors<
typeof individualSchema.shape
>;
return (
<TextField
{...field}
label="Ad Soyad*"
variant="outlined"
fullWidth
error={!!individualSchErrors.name}
helperText={individualSchErrors.name?.message || ' '}
/>
);
}}
/>
)}
Demo @ StackBlitz