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

求助:使用z.infer时Zod自动将所有字段设为可选的问题

Zod z.infer 推导类型时所有字段变为可选的问题解决

问题详情

  • 使用z.infer从Zod校验器推导类型时,所有字段被自动标记为可选
  • 类型定义在未编译的types包中,代码如下:
import type { z } from 'zod';
import type { cardValidator, imageBlockValidator, textBlockValidator } from 'validators';

export type ValidatedCard = z.infer<typeof cardValidator>;
export type ValidatedTextBlock = z.infer<typeof textBlockValidator>;
export type ValidatedImageBlock = z.infer<typeof imageBlockValidator>;
  • types包已配置strict: true的tsconfig,utils包的tsconfig也开启了strict: true,但问题依旧
  • 导致应用编译失败:可选值被传入要求必填类型的函数或变量
  • 版本信息:TypeScript 4.9.3,`validators`和`types`包的Zod版本均为3.20.2

校验器代码

import { z } from 'zod';

export const textBlockValidator = z.object({
  type: z.literal('text'),
  content: z.string(),
  id: z.string(),
});

export const imageBlockValidator = z.object({
  type: z.literal('image'),
  url: z.string(),
  alt: z.string().optional(),
  id: z.string(),
});

export const cardValidator = z.object({
  id: z.string(),
  title: z.string(),
  blocks: z.array(z.union([textBlockValidator, imageBlockValidator])),
});

解决步骤

1. 修正类型导入方式

你在types包里用了import type导入校验器,但校验器是运行时值,不是类型。这种导入会让TypeScript丢失值的类型上下文,导致推导异常。改成直接导入(去掉type):

import { z } from 'zod';
import { cardValidator, imageBlockValidator, textBlockValidator } from 'validators';

export type ValidatedCard = z.infer<typeof cardValidator>;
export type ValidatedTextBlock = z.infer<typeof textBlockValidator>;
export type ValidatedImageBlock = z.infer<typeof imageBlockValidator>;

2. 确认monorepo依赖配置

  • 确保types包的package.json里把validators声明为dependencies(不是devDependencies),保证utils包能正确获取校验器的类型
  • 检查types包的tsconfig是否开启declaration: true,确保导出的类型能被其他包识别

3. 验证Zod版本一致性

在项目根目录执行命令,确认所有包的Zod版本完全一致:

# npm
npm list zod
# pnpm
pnpm list zod

版本不一致可能导致类型推导出现奇怪问题。

4. 清理缓存并重新构建

  • 删除所有包的dist目录和node_modules/.cache文件夹
  • 重新安装依赖:npm install 或 pnpm install
  • 重新编译所有相关包

验证结果

修改后,推导的ValidatedCard类型应该只有alt字段是可选,其他字段均为必填,符合校验器定义:

type ValidatedCard = {
  id: string;
  title: string;
  blocks: (
    | { type: 'text'; content: string; id: string }
    | { type: 'image'; url: string; alt?: string | undefined; id: string }
  )[];
};

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.03 00:41:13