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

Zod如何为必填字段设置undefined作为默认值

Zod 实现必填数字字段空默认值的最优方案

核心问题本质是表单控件的输入值类型和Zod期望的类型不匹配:数字输入框为空时,表单库拿到的返回值是空字符串''而非undefined,原生z.number()既不接受空字符串输入,也无法区分「用户未输入」和「输入值为0」的场景,才会出现强制要求设置默认值的问题。

实现方案

不需要修改字段的必填属性,也不需要给数字字段设置无意义的默认值(比如0),通过自定义校验逻辑兼容空输入场景即可,完全满足所有需求:

import { z } from 'zod';

// 可复用的必填数字字段校验规则
const requiredNumber = z
  .union([z.string(), z.number(), z.null(), z.undefined()])
  .superRefine((val, ctx) => {
    // 识别所有空输入场景,触发必填校验
    if (val === '' || val === null || val === undefined) {
      ctx.addIssue({
        code: z.ZodIssueCode.custom,
        message: '该字段为必填项',
        fatal: true
      });
      return z.NEVER;
    }
    // 非空值校验是否为合法数字,转换为数字类型输出
    const numVal = Number(val);
    if (isNaN(numVal)) {
      ctx.addIssue({
        code: z.ZodIssueCode.custom,
        message: '请输入有效的数字'
      });
      return;
    }
    return numVal;
  });

const schema = z.object({
  host: z.string().default('Host'), // 其余字段正常配置默认值即可
  port: requiredNumber // port字段无需设置default
});

方案匹配的特性

  • port字段为强必填:空字符串、null、undefined三类空输入都会直接触发校验失败,不会自动填充任何默认值
  • 校验通过的port值一定是数字类型,符合类型要求
  • 新增场景下表单默认值不需要配置port字段,或者显式设为''即可,输入框默认展示为空,强制用户主动输入
  • 编辑场景下直接传入接口返回的数字类型port值做回填,schema可正常识别无报错

避坑提醒

  • 不要直接使用z.coerce.number():该方法会把空字符串''强制转换为0,会绕过必填校验,出现空提交时port值被自动设为0的问题
  • 不要为了兼容空输入把port设为.optional():会导致空提交时port值为undefined也能通过校验,不符合必填要求
  • 该逻辑可复用到所有非字符串类型的必填字段(比如日期、布尔值选择器等),只需要调整对应的值转换和校验规则即可,不需要为了表单交互给业务字段设置无意义的默认占位值。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.02 05:18:25