Skip to content
This repository was archived by the owner on Mar 1, 2026. It is now read-only.

Commit 154ba29

Browse files
authored
fix(orm): incorrect result type when "_count" is nested inside "include" (#589)
1 parent f54093d commit 154ba29

File tree

3 files changed

+70
-1
lines changed

3 files changed

+70
-1
lines changed

packages/orm/src/client/crud-types.ts

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -214,7 +214,11 @@ export type ModelResult<
214214
ModelFieldIsOptional<Schema, Model, Key>,
215215
FieldIsArray<Schema, Model, Key>
216216
>;
217-
}
217+
} & ('_count' extends keyof I
218+
? I['_count'] extends false | undefined
219+
? {}
220+
: { _count: SelectCountResult<Schema, Model, I['_count']> }
221+
: {})
218222
: Args extends { omit: infer O } & Record<string, unknown>
219223
? DefaultModelResult<Schema, Model, O, Options, false, false>
220224
: DefaultModelResult<Schema, Model, undefined, Options, false, false>,

tests/e2e/orm/client-api/find.test.ts

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1122,6 +1122,52 @@ describe('Client find tests ', () => {
11221122
});
11231123
});
11241124

1125+
it('supports _count inside include', async () => {
1126+
const user = await createUser(client, 'u1@test.com');
1127+
await createPosts(client, user.id);
1128+
1129+
// Test _count with select inside include
1130+
const result = await client.user.findFirst({
1131+
include: {
1132+
posts: { select: { title: true } },
1133+
_count: { select: { posts: true } },
1134+
},
1135+
});
1136+
1137+
expect(result).toBeDefined();
1138+
expect(result?.posts).toHaveLength(2);
1139+
expect(result?.posts[0]).toHaveProperty('title');
1140+
// TypeScript should recognize _count property exists
1141+
expect(result?._count).toBeDefined();
1142+
expect(result?._count.posts).toBe(2);
1143+
1144+
// Test _count with boolean true inside include
1145+
const result2 = await client.user.findFirst({
1146+
include: {
1147+
posts: true,
1148+
_count: true,
1149+
},
1150+
});
1151+
1152+
expect(result2).toBeDefined();
1153+
expect(result2?.posts).toHaveLength(2);
1154+
expect(result2?._count).toBeDefined();
1155+
expect(result2?._count.posts).toBe(2);
1156+
1157+
// Test _count with filtered posts inside include
1158+
const result3 = await client.user.findFirst({
1159+
include: {
1160+
posts: { where: { published: true } },
1161+
_count: { select: { posts: { where: { published: true } } } },
1162+
},
1163+
});
1164+
1165+
expect(result3).toBeDefined();
1166+
expect(result3?.posts).toHaveLength(1);
1167+
expect(result3?._count).toBeDefined();
1168+
expect(result3?._count.posts).toBe(1);
1169+
});
1170+
11251171
it('supports $expr', async () => {
11261172
await createUser(client, 'yiming@gmail.com');
11271173
await createUser(client, 'yiming@zenstack.dev');

tests/e2e/orm/schemas/typing/typecheck.ts

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -162,6 +162,25 @@ async function find() {
162162
})
163163
).profile?.region?.city;
164164

165+
// _count inside include should be properly typed
166+
const includeWithCount = await client.user.findFirst({
167+
include: {
168+
posts: { select: { title: true } },
169+
_count: { select: { posts: true } },
170+
},
171+
});
172+
console.log(includeWithCount?.posts[0]?.title);
173+
console.log(includeWithCount?._count.posts);
174+
175+
const includeWithCountTrue = await client.user.findFirst({
176+
include: {
177+
posts: true,
178+
_count: true,
179+
},
180+
});
181+
console.log(includeWithCountTrue?.posts[0]?.title);
182+
console.log(includeWithCountTrue?._count.posts);
183+
165184
(
166185
await client.user.findFirstOrThrow({
167186
select: {

0 commit comments

Comments
 (0)