P
Prisma5mo ago
Duck

Dynamic select column doesn't return the correct type

Hello, I have an issue with a particular query I'm trying to run. I have a relation model called 'Posts' and in this particular query I only want to include posts if a specific condition is met before hand (i.e. condition ? { /* select */ } : false). When doing this the return type changes, seek below result.
const user = await this.prismaService.users.findFirst({
select: {
id: true,
username: true,
email: userViewFlag === "me",
bio: true,
private: true,
createdAt: true,
Posts:
userViewFlag !== "unauthenticated"
? {
select: {
_count: {
select: { Comments: true, Likes: true },
},
id: true,
title: true,
description: true,
createdAt: true,
updatedAt: true,
},
where: {
deletedAt: null,
},
take: 20,
}
: false,
},
where: {
id,
},
});
const user = await this.prismaService.users.findFirst({
select: {
id: true,
username: true,
email: userViewFlag === "me",
bio: true,
private: true,
createdAt: true,
Posts:
userViewFlag !== "unauthenticated"
? {
select: {
_count: {
select: { Comments: true, Likes: true },
},
id: true,
title: true,
description: true,
createdAt: true,
updatedAt: true,
},
where: {
deletedAt: null,
},
take: 20,
}
: false,
},
where: {
id,
},
});
This is the return type
const user: {
id: number;
username: string;
email: string;
bio: string | null;
private: boolean;
createdAt: Date;
Posts: {
id: number;
createdAt: Date;
updatedAt: Date;
title: string;
description: string;
deletedAt: Date | null;
userId: number;
}[];
} | null
const user: {
id: number;
username: string;
email: string;
bio: string | null;
private: boolean;
createdAt: Date;
Posts: {
id: number;
createdAt: Date;
updatedAt: Date;
title: string;
description: string;
deletedAt: Date | null;
userId: number;
}[];
} | null
But if I remove the userViewFlag !== "unauthenticated" check this is the type output (the expect output).
const user: {
id: number;
username: string;
email: string;
bio: string | null;
private: boolean;
createdAt: Date;
Posts: {
id: number;
createdAt: Date;
updatedAt: Date;
_count: {
Comments: number;
Likes: number;
};
title: string;
description: string;
}[];
} | null
const user: {
id: number;
username: string;
email: string;
bio: string | null;
private: boolean;
createdAt: Date;
Posts: {
id: number;
createdAt: Date;
updatedAt: Date;
_count: {
Comments: number;
Likes: number;
};
title: string;
description: string;
}[];
} | null
Curious if there is something I can do to make this work a better or if I may have missed something.
5 Replies
Prisma AI Help
Prisma AI Help5mo ago
You decided to hold for human wisdom. We'll chime in soon! Meanwhile, #ask-ai is there if you need a quick second opinion.
Duck
DuckOP5mo ago
I'm on version 6.6.0 FYI I think the workarounds that don't involve doing what I am above would be - Always including it and filtering it out in a DTO - Get the posts in a separate query Would prefer the types for this particular query to yield what I expect. I also notice that it isn't able to decern the type for email which in my eyes would be email? string. Just small things. Guess not
Nurul
Nurul5mo ago
Hey! It seems that you are running into this issue: https://github.com/prisma/prisma/issues/20871 The problem occurs because TypeScript can't infer that the Posts field might be absent in the result based on the runtime condition. One workaround could be to split your logic into two separate queries:
let user;
if (userViewFlag !== "unauthenticated") {
user = await this.prismaService.users.findFirst({
select: {
id: true,
username: true,
email: userViewFlag === "me",
bio: true,
private: true,
createdAt: true,
Posts: {
select: {
_count: {
select: { Comments: true, Likes: true },
},
id: true,
title: true,
description: true,
createdAt: true,
updatedAt: true,
},
where: {
deletedAt: null,
},
take: 20,
},
},
where: { id },
});
} else {
user = await this.prismaService.users.findFirst({
select: {
id: true,
username: true,
email: userViewFlag === "me",
bio: true,
private: true,
createdAt: true,
},
where: { id },
});
}
let user;
if (userViewFlag !== "unauthenticated") {
user = await this.prismaService.users.findFirst({
select: {
id: true,
username: true,
email: userViewFlag === "me",
bio: true,
private: true,
createdAt: true,
Posts: {
select: {
_count: {
select: { Comments: true, Likes: true },
},
id: true,
title: true,
description: true,
createdAt: true,
updatedAt: true,
},
where: {
deletedAt: null,
},
take: 20,
},
},
where: { id },
});
} else {
user = await this.prismaService.users.findFirst({
select: {
id: true,
username: true,
email: userViewFlag === "me",
bio: true,
private: true,
createdAt: true,
},
where: { id },
});
}
GitHub
Conditional select and include not inferring expected type · ...
Bug description Our backend API has routes where we can optionally perform what the include API does. For example fetch user and optionally include posts written by this user. I expect the inferred...
Duck
DuckOP5mo ago
I can confirm both the .findFirst calls have the correct return type. Maybe there's something on my tsconfig.
No description
Duck
DuckOP5mo ago
I thought it might have been the order so I flipped the if statement around and it's the same return type. I feel like I'm losing my mind lol.

Did you find this page helpful?