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

TypeScript合并泛型Zod Schema出现类型错误,如何解决?

解决Zod Schema合并后对象类型推断不匹配问题

问题分析

你遇到的类型错误本质是Zod内部对对象Schema的可选/必填属性做了复杂的类型转换(比如addQuestionMarks这类内部工具类型),导致TypeScript无法自动识别手动扩展的对象与合并后Schema的推断类型是兼容的。虽然类型断言可以跳过检查,但我们可以通过明确类型定义来让TypeScript正确推断。

解决方案

核心思路是手动定义合并后的类型为原Schema推断类型与版本Schema推断类型的交叉类型,而不是依赖合并后Schema的自动推断。这样TypeScript能清晰识别扩展后的对象符合该类型,同时合并后的Schema依然保持运行时校验能力。

修改后的代码如下:

import { z } from "zod";

// 版本化项的通用Schema
const versioningSchema = z.object({
  version: z.number(),
});

export const addVersioningToItem = <U extends z.ZodRawShape>(
  originalSchema: z.ZodObject<U>,
  item: z.infer<typeof originalSchema>,
) => {
  // 手动定义合并后的类型:原类型与版本类型的交叉
  type CombinedSchema = z.infer<typeof originalSchema> & z.infer<typeof versioningSchema>;

  const mergedSchema = originalSchema.merge(versioningSchema);

  // 此时TypeScript能正确识别该对象符合CombinedSchema类型
  const itemWithVersioning: CombinedSchema = {
    ...item,
    version: 1,
  };

  return { mergedSchema, itemWithVersioning };
};

为什么这样有效

  1. 交叉类型A & B直接明确了合并后类型的结构,TypeScript可以轻松验证{...item, version:1}满足该结构
  2. mergedSchema的推断类型与CombinedSchema完全等价,后续用mergedSchema做运行时校验不会有任何问题
  3. 避免了依赖Zod内部复杂的类型转换逻辑,让类型推断更直接、可靠

额外优化(可选)

如果想进一步约束原Schema不能包含version属性(避免冲突),可以修改泛型约束:

export const addVersioningToItem = <U extends z.ZodRawShape & { version?: never }>(
  originalSchema: z.ZodObject<U>,
  item: z.infer<typeof originalSchema>,
) => {
  // ... 其余代码不变
};

这样如果传入的原Schema已经有version属性,TypeScript会提前报错,避免运行时的Schema合并冲突。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.14 11:13:10