如何在Prisma中为嵌套Include返回正确的TypeScript类型?
Prisma嵌套Include参数化后类型丢失问题解决
问题背景
数据模型定义如下:
model Foo { id String @id @default(cuid()) bar Bar[] } model Bar { id String @id @default(cuid()) foo Foo @relation(fields: [fooId], references: [id], onDelete: Cascade, onUpdate: Cascade) fooId String baz Baz[] } model Baz { id String @id @default(cuid()) bar Bar @relation(fields: [barId], references: [id], onDelete: Cascade, onUpdate: Cascade) barId String }
当直接在函数内写死include配置时,TypeScript能正确推导返回类型,识别嵌套的baz字段:
async function getFooById(id: Foo['id']) { return prisma.foo.findUnique({ where: { id }, include: { bar: { include: { baz: true } } }, }) } const foo = await getFooById('123') if (foo !== null) { const baz = foo.bar[0].baz // 类型正常识别 }
但将include参数化后,类型推导失效,无法识别foo.bar[0].baz:
import type { DefaultArgs } from '@prisma/client/runtime/library.js' async function getFooById( id: Foo['id'], { include }: { include: Prisma.FooInclude<DefaultArgs> } = { include: {} }, ) { return prisma.foo.findUnique({ where: { id }, include, }) } const foo = await getFooById('123', { include: { bar: { include: { baz: true } } } }) if (foo !== null) { // 错误:baz不存在于foo.bar[0]类型上 const baz = foo.bar[0].baz }
尝试泛型写法也未解决:
async function getFooById<ExtArgs extends Types.Extensions.InternalArgs = Types.Extensions.DefaultArgs>( id: Foo['id'], { include }: { include: Prisma.FooInclude<ExtArgs> } = { include: {} }, ) { // … }
使用版本:Prisma 5.8.0,TypeScript 5.3.3
解决方案
要让TypeScript正确推导参数化include后的返回类型,需要利用Prisma提供的泛型类型工具,将include参数的类型与函数返回类型绑定:
正确的泛型写法
import type { Prisma, Foo } from '@prisma/client' async function getFooById<T extends Prisma.FooInclude>( id: Foo['id'], { include }: { include?: T } = {} ): Promise<Prisma.FooGetPayload<{ include: T }> | null> { return prisma.foo.findUnique({ where: { id }, include, }) }
使用示例
const foo = await getFooById('123', { include: { bar: { include: { baz: true } } } }) if (foo !== null) { const baz = foo.bar[0].baz // 类型正确识别,无报错 }
原理说明
T extends Prisma.FooInclude:约束泛型T为Foo模型允许的include配置类型Prisma.FooGetPayload<{ include: T }>:Prisma提供的类型工具,根据传入的include配置,自动推导对应的返回数据类型- 显式指定返回类型为
Promise<... | null>:匹配findUnique可能返回null的特性
这样就能让TypeScript根据传入的include参数,动态推导函数返回的Foo对象的完整类型,包括所有嵌套关联字段。
内容的提问来源于stack exchange,提问作者Thomas Luzat
相关产品推荐
相关产品推荐

