求助:使用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
相关产品推荐
相关产品推荐

