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

如何为可选数字属性设置空字符串作为默认值?

问题与解决方案

问题背景

表单字段要求:可留空,若填写则必须是数字。结合react-hook-form与Zod时遇到两个矛盾点:

  1. 必须设置默认值,否则React会警告「受控组件不能转为非受控组件」;
  2. 设置空字符串""作为optionalNumber的默认值时,TypeScript报错,提示类型不兼容。

原Zod Schema定义:

const mySchema = z.object({
  optionalNumber: z.literal('')
     .or(z.coerce.number())
     .transform(val => val === '' ? undefined : val)
})

设置默认值时的TypeScript报错:

const form = useForm<z.infer<typeof mySchema>>({
  resolver: zodResolver(mySchema),
  defaultValues: {
    optionalNumber: '' // TS2322: Type string is not assignable to type number
  }
});

报错原因:z.infer<T>获取的是Zod解析后的输出类型,而defaultValues需要匹配Zod的输入类型,两者不匹配导致类型校验失败。

解决方案

利用Zod的z.input<T>类型推断,明确指定useForm的泛型为Schema的输入类型,即可解决类型冲突:

优化后的Zod Schema

const mySchema = z.object({
  optionalNumber: z.string().optional().transform((val) => {
    if (val === '' || typeof val === 'undefined') {
      return undefined;
    } else {
      return parseInt(val, 10);
    }
  }).refine((val) => 
    typeof val === 'undefined' || val >= 0, { 
      message: "价格不能小于0"
  })
})

正确配置useForm

const form = useForm<z.input<typeof mySchema>>({ 
  resolver: zodResolver(mySchema),
  defaultValues: {
    optionalNumber: ''
  }
});

内容的提问来源于stack exchange,提问作者dschulten

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.14 22:47:42