使用Prisma生成类型配合Server Actions时的类型错误
问题分析与解决方案
核心原因
你遇到的类型错误,本质是前端传入的数据结构与Prisma自动生成的ResidentCreateInput类型不匹配:
- Prisma生成的
ResidentCreateInput中,ethnicity字段的类型是EthnicityCreateNestedOneWithoutResidentsInput,这个类型只允许包含connect/create/connectOrCreate这类关联操作结构,而非直接的name字段。 - 但你传入的
data.ethnicity是{name: "example"},属于Ethnicity实体的字段结构,和Prisma要求的关联操作类型完全不符,因此TypeScript会报错name不存在。
解决方案
你完全可以继续使用Prisma的类型系统,只需根据前端传入的数据结构做适配,以下是两种可行方案:
方案一:自定义输入类型(推荐,无需修改前端)
针对前端传入的结构,自定义一个输入类型,再在Server Action中转换为Prisma需要的格式:
- 定义适配前端的输入类型:
// 替换原有的ResidentCreateInput参数类型 type CreateResidentInput = Omit<ResidentCreateInput, 'ethnicity'> & { ethnicity: { name: string }; };
- 修改Server Action的参数与逻辑:
export async function createResident( data: CreateResidentInput, userId: string, ): Promise<ResidentWithHomes> { try { const resident = await prisma.resident.create({ data: { // 展开除ethnicity外的所有字段 ...(data as Omit<CreateResidentInput, 'ethnicity'>), createdBy: { connect: { id: userId } }, // 将前端传入的ethnicity.name转换为Prisma需要的connectOrCreate结构 ethnicity: { connectOrCreate: { where: { name: data.ethnicity.name }, create: { name: data.ethnicity.name }, }, }, // ... 其他代码 }); return resident; } catch (error) { // 错误处理逻辑不变 if (error instanceof Prisma.PrismaClientKnownRequestError) { throw new Error(`Database request failed: ${error.message}`); } else if (error instanceof Prisma.PrismaClientValidationError) { throw new Error( `Validation failed for the data provided: ${error.message}`, ); } else { throw new Error('An unexpected error occurred while creating a resident'); } } }
方案二:调整前端数据结构(适配Prisma内置类型)
如果允许修改前端传入的数据,让其符合ResidentCreateInput的要求,那么可以直接使用Prisma的内置类型:
前端需要传入的结构改为:
{ "firstName": "example", "middleName": "example", "lastName": "example", // 按照Prisma关联操作类型传入 "ethnicity": { "connectOrCreate": { "where": { "name": "example" }, "create": { "name": "example" } } }, // ... 其他字段 }
此时Server Action可简化为:
export async function createResident( data: ResidentCreateInput, userId: string, ): Promise<ResidentWithHomes> { try { const resident = await prisma.resident.create({ data: { ...data, createdBy: { connect: { id: userId } }, // 无需再单独处理ethnicity,data中已包含正确结构 // ... 其他代码 }); return resident; } catch (error) { // 错误处理逻辑不变 } }
内容的提问来源于stack exchange,提问作者Nick Shoemake
相关产品推荐
相关产品推荐

