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

Remix项目使用Prisma Zod Generator遇ZodUnion解析错误

Remix + Prisma Zod Generator 解析FormData报错问题

问题背景

在Remix项目中集成Prisma Zod Generator工具时,更新模型遇到解析错误。定义的Prisma模型如下:

model TextContent {
  content   Content @relation(fields: [contentId], references: [id], onDelete: Cascade)
  contentId String  @id
  text      String
}

使用生成的TextContentUncheckedUpdateInputObjectSchema配合remix-params-helper的getFormDataOrFail方法解析FormData时,触发以下错误:

Error: Unexpected type ZodUnion for key contentId
    at processDef (my-app/node_modules/remix-params-helper/dist/cjs/helper.js:179:15)
    at processDef (my-app/node_modules/remix-params-helper/dist/cjs/helper.js:162:9)
    at parseParams (my-app/node_modules/remix-params-helper/dist/cjs/helper.js:36:9)
    at getParamsInternal (my-app/node_modules/remix-params-helper/dist/cjs/helper.js:54:9)
    at getFormDataOrFail (my-app/node_modules/remix-params-helper/dist/cjs/helper.js:120:20)
    at processTicksAndRejections (node:internal/process/task_queues:96:5)
    at action (my-app/app/routes/contents.$contentId.tsx:12:15)
    at Object.callRouteActionRR (my-app/build/server.js:39649:20)
    at callLoaderOrAction (my-app/build/server.js:38772:20)
    at submit (my-app/build/server.js:38365:20)

已确认FormData中的contentId和text均为字符串值,且contentId同时通过路由params和FormData传递。

原因分析

Prisma Zod Generator生成的UncheckedUpdateInput类型对应的Zod Schema中,contentId字段是字符串与关联对象的联合类型(ZodUnion)——这是因为UncheckedUpdateInput允许两种更新方式:直接传入外键ID字符串,或者传入关联的Content对象进行嵌套更新。但remix-params-helper工具目前不支持解析ZodUnion类型,因此触发了错误。

此外,你的更新场景中contentId已经通过路由params获取,完全不需要从FormData中传递该字段,这也是导致多余解析错误的原因之一。

解决方案

方案1:裁剪生成的Schema,保留必要字段

使用Zod的pick方法,只提取需要验证的text字段,避免解析不需要的contentId字段:

export async function action({ request, params }: ActionArgs) {
  // 仅保留text字段用于验证
  const schema = TextContentUncheckedUpdateInputObjectSchema.pick({ text: true });
  const data = await getFormDataOrFail(request, schema);
  
  await prisma.textContent.update({
    data,
    where: {
      contentId: params.contentId
    }
  });
  return null;
}

方案2:自定义Zod Schema替代生成的类型

如果需要更灵活的验证规则,直接编写自定义Zod Schema,绕开生成的Union类型问题:

import { z } from "zod";

// 自定义更新验证规则
const UpdateTextContentSchema = z.object({
  text: z.string(),
});

export async function action({ request, params }: ActionArgs) {
  const data = await getFormDataOrFail(request, UpdateTextContentSchema);
  
  await prisma.textContent.update({
    data,
    where: {
      contentId: params.contentId
    }
  });
  return null;
}

方案3:强制覆盖contentId的Schema类型(若需传递该字段)

如果业务场景确实需要从FormData中传递contentId,可以手动覆盖该字段的Schema类型,将其强制指定为字符串:

export async function action({ request, params }: ActionArgs) {
  const schema = TextContentUncheckedUpdateInputObjectSchema.extend({
    contentId: z.string(),
  });
  const data = await getFormDataOrFail(request, schema);
  
  await prisma.textContent.update({
    data,
    where: {
      contentId: data.contentId // 或使用params.contentId,根据业务场景选择
    }
  });
  return null;
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.20 20:35:07