shadcn/ui FormField组件control属性的Type类型错误排查求助
大家好,我最近在使用shadcn/ui的FormField组件时碰到了一个TypeScript类型不兼容的问题,折腾了好一阵没捋明白,想请各位帮忙看看问题出在哪。
先把相关代码贴出来:
1. Zod Schema 定义
export const CourseSchema = z.object({ title: requiredString.max(100, { error: 'The title must not be longer than 100 characters!' }), briefDescription: requiredString.max(200, { error: 'The brief description must not be longer than 200 characters!', }), description: requiredString.max(2000, { error: 'The description must not be longer than 2000 characters!', }), duration: z.coerce .number<string>() .positive({ error: 'Only positive numbers are allowed!' }) .int({ error: 'Only integers are allowed!' }), price: z.coerce .number<string>() .positive({ error: 'Only positive numbers are allowed!' }) .int({ error: 'Only integers are allowed!' }), categoryName: requiredString, level: z.enum(Object.values(CourseLevel)), status: z.enum(Object.values(CourseStatus)), });
注:CourseLevel和CourseStatus是Prisma自动生成的字符串枚举类型。
2. Form 组件代码
export default function CreateCourseForm() { const form = useForm({ resolver: zodResolver(CourseSchema), defaultValues: { title: '', briefDescription: '', description: '', duration: '', price: '', categoryName: '', level: Object.values(CourseLevel)[0], status: Object.values(CourseStatus)[0], }, }); function onSubmit(values: z.output<typeof CourseSchema>) { console.log(values); } return ( <Form {...form}> <form onSubmit={form.handleSubmit(onSubmit)} className="space-y-8"> <FormField control={form.control} name="title" render={({ field }) => ( <FormItem> <FormLabel>Title</FormLabel> <FormControl> <Input placeholder="Title of your course" {...field} /> </FormControl> <FormMessage /> </FormItem> )} /> <ButtonLoading type="submit">Submit</ButtonLoading> </form> </Form> ); }
遇到的具体类型错误
现在FormField的control属性触发了TypeScript报错,错误信息如下:
Type 'Control<{ title: string; briefDescription: string; description: string; duration: string; price: string; categoryName: string; level: "BEGINNER" | "INTERMEDIATE" | "ADVANCED"; status: "DRAFT" | "PUBLISHED" | "ARCHIVED"; }, unknown, { ...; }>' is not assignable to type 'Control<{ title: string; briefDescription: string; description: string; duration: string; price: string; categoryName: string; level: "BEGINNER" | "INTERMEDIATE" | "ADVANCED"; status: "DRAFT" | "PUBLISHED" | "ARCHIVED"; }, any, { ...; }>'.
The types of '_options.resolver' are incompatible between these types.
Type 'Resolver<{ title: string; briefDescription: string; description: string; duration: string; price: string; categoryName: string; level: "BEGINNER" | "INTERMEDIATE" | "ADVANCED"; status: "DRAFT" | "PUBLISHED" | "ARCHIVED"; }, unknown, { ...; }> | undefined' is not assignable to type 'Resolver<{ title: string; briefDescription: string; description: string; duration: string; price: string; categoryName: string; level: "BEGINNER" | "INTERMEDIATE" | "ADVANCED"; status: "DRAFT" | "PUBLISHED" | "ARCHIVED"; }, any, { ...; }> | undefined'.
Type 'Resolver<{ title: string; briefDescription: string; description: string; duration: string; price: string; categoryName: string; level: "BEGINNER" | "INTERMEDIATE" | "ADVANCED"; status: "DRAFT" | "PUBLISHED" | "ARCHIVED"; }, unknown, { ...; }>' is not assignable to type 'Resolver<{ title: string; briefDescription: string; description: string; duration: string; price: string; categoryName: string; level: "BEGINNER" | "INTERMEDIATE" | "ADVANCED"; status: "DRAFT" | "PUBLISHED" | "ARCHIVED"; }, any, { ...; }>'.
Type 'number' is not assignable to type 'string'.ts(2322)
controller.d.ts(24, 5): The expected type comes from property 'control' which is declared here on type 'IntrinsicAttributes & { render: ({ field, fieldState, formState, }: { field: ControllerRenderProps<{ title: string; briefDescription: string; description: string; duration: string; price: string; categoryName: string; level: "BEGINNER" | ... 1 more ... | "ADVANCED"; status: "DRAFT" | ... 1 more ... | "ARCHIVED"; }, ...'
(property) control?: Control<{ title: string; briefDescription: string; description: string; duration: string; price: string; categoryName: string; level: "BEGINNER" | "INTERMEDIATE" | "ADVANCED"; status: "DRAFT" | "PUBLISHED" | "ARCHIVED"; }, any, { title: string; briefDescription: string; description: string; duration: string; price: string; categoryName: string; level: "BEGINNER" | "INTERMEDIATE" | "ADVANCED"; status: "DRAFT"..."
我隐约感觉是duration和price字段的类型转换问题——Zod里用了z.coerce.number()把输入的字符串转成数字,但表单默认值是字符串类型,导致React Hook Form的Control类型和shadcn/ui的FormField期望的类型不匹配。不过具体该怎么调整才能解决这个类型错误,还是有点摸不着头脑,有没有大佬能给点思路或者解决方案呀?
内容来源于stack exchange

