You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

shadcn/ui FormField组件control属性的Type类型错误排查求助

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.04.07 07:14:29