P
Prisma6d 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.
3 Replies
Prisma AI Help
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
DuckOP4d 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
Nurul4d 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...

Did you find this page helpful?