Skip to content

Commit 182e996

Browse files
committed
Fixes JsonAgg type definition
Updates the type definition for JsonAgg aggregate function to correctly infer the element type of the resulting array. The previous type definition used `Selectable` which was too broad. The updated type definition now uses `SelectType` to extract the correct type and `ShallowDehydrateValue` to remove `undefined` from the type. The change is accompanied by a fix in the typings tests.
1 parent 4a90256 commit 182e996

2 files changed

Lines changed: 80 additions & 35 deletions

File tree

src/query-builder/function-module.ts

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ import { AggregateFunctionBuilder } from './aggregate-function-builder.js'
2828
import { SelectQueryBuilderExpression } from '../query-builder/select-query-builder-expression.js'
2929
import { isString } from '../util/object-utils.js'
3030
import { parseTable } from '../parser/table-parser.js'
31-
import { Selectable } from '../util/column-type.js'
31+
import { Selectable, SelectType } from '../util/column-type.js'
3232

3333
/**
3434
* Helpers for type safe SQL function calls.
@@ -732,7 +732,10 @@ export interface FunctionModule<DB, TB extends keyof DB> {
732732
): AggregateFunctionBuilder<
733733
DB,
734734
TB,
735-
ShallowDehydrateValue<ExtractTypeFromStringReference<DB, TB, RE>>[] | null
735+
| ShallowDehydrateValue<
736+
SelectType<ExtractTypeFromStringReference<DB, TB, RE>>
737+
>[]
738+
| null
736739
>
737740

738741
/**

test/typings/test-d/postgres-json.test-d.ts

Lines changed: 75 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -5,9 +5,8 @@ import {
55
jsonObjectFrom,
66
sql,
77
ExpressionBuilder,
8-
Selectable,
98
} from '..'
10-
import { Database, Pet } from '../shared'
9+
import { Database } from '../shared'
1110
import { expectType } from 'tsd'
1211

1312
async function testPostgresJsonSelects(db: Kysely<Database>) {
@@ -78,54 +77,85 @@ async function testPostgresConditionalJsonSelects(db: Kysely<Database>) {
7877

7978
async function testPostgresJsonAgg(db: Kysely<Database>) {
8079
const r1 = await db
81-
.selectFrom('person')
82-
.innerJoin('pet', 'pet.owner_id', 'person.id')
83-
.select((eb) => ['first_name', eb.fn.jsonAgg('pet').as('pets')])
84-
.groupBy('person.first_name')
80+
.selectFrom('pet')
81+
.innerJoin('person', 'pet.owner_id', 'person.id')
82+
.select((eb) => ['pet.name', eb.fn.jsonAgg('person').as('people')])
83+
.groupBy('pet.name')
8584
.execute()
8685

8786
expectType<
8887
{
89-
first_name: string
90-
pets: Selectable<Pet>[]
88+
name: string
89+
people: {
90+
id: number
91+
first_name: string
92+
last_name: string | null
93+
age: number
94+
gender: 'male' | 'female' | 'other'
95+
marital_status: 'single' | 'married' | 'divorced' | 'widowed' | null
96+
modified_at: string
97+
deleted_at: string | null
98+
}[]
9199
}[]
92100
>(r1)
93101

94102
const r2 = await db
95-
.selectFrom('person')
103+
.selectFrom('pet')
96104
.select((eb) => [
97-
'first_name',
105+
'name',
98106
eb
99-
.selectFrom('pet')
100-
.select((eb) => eb.fn.jsonAgg('pet').as('pet'))
107+
.selectFrom('person')
108+
.select((eb) => eb.fn.jsonAgg('person').as('people'))
101109
.whereRef('pet.owner_id', '=', 'person.id')
102-
.as('pets'),
110+
.as('people'),
103111
])
104112
.execute()
105113

106114
expectType<
107115
{
108-
first_name: string
109-
pets: Selectable<Pet>[] | null
116+
name: string
117+
people:
118+
| {
119+
id: number
120+
first_name: string
121+
last_name: string | null
122+
age: number
123+
gender: 'male' | 'female' | 'other'
124+
marital_status: 'single' | 'married' | 'divorced' | 'widowed' | null
125+
modified_at: string
126+
deleted_at: string | null
127+
}[]
128+
| null
110129
}[]
111130
>(r2)
112131

113132
const r3 = await db
114-
.selectFrom('person')
133+
.selectFrom('pet')
115134
.select((eb) => [
116-
'first_name',
135+
'name',
117136
eb
118-
.selectFrom('pet')
119-
.select((eb) => eb.fn.jsonAgg(eb.table('pet')).as('pet'))
137+
.selectFrom('person')
138+
.select((eb) => eb.fn.jsonAgg(eb.table('person')).as('people'))
120139
.whereRef('pet.owner_id', '=', 'person.id')
121-
.as('pets'),
140+
.as('people'),
122141
])
123142
.execute()
124143

125144
expectType<
126145
{
127-
first_name: string
128-
pets: Selectable<Pet>[] | null
146+
name: string
147+
people:
148+
| {
149+
id: number
150+
first_name: string
151+
last_name: string | null
152+
age: number
153+
gender: 'male' | 'female' | 'other'
154+
marital_status: 'single' | 'married' | 'divorced' | 'widowed' | null
155+
modified_at: string
156+
deleted_at: string | null
157+
}[]
158+
| null
129159
}[]
130160
>(r3)
131161

@@ -171,31 +201,43 @@ async function testPostgresJsonAgg(db: Kysely<Database>) {
171201
}>(r4)
172202

173203
const r5 = await db
174-
.selectFrom('person')
175-
.innerJoin('pet', 'pet.owner_id', 'person.id')
176-
.select((eb) => ['first_name', eb.fn.jsonAgg('owner_id').as('pet_names')])
177-
.groupBy('person.first_name')
204+
.selectFrom('pet')
205+
.innerJoin('person', 'pet.owner_id', 'person.id')
206+
.select((eb) => [
207+
'name',
208+
eb.fn.jsonAgg('person.modified_at').as('modified_at'),
209+
])
210+
.groupBy('name')
178211
.execute()
179212

180213
expectType<
181214
{
182-
first_name: string
183-
pet_names: number[] | null
215+
name: string
216+
modified_at: string[] | null
184217
}[]
185218
>(r5)
186219
}
187220

188221
async function testPostgresToJson(db: Kysely<Database>) {
189222
const r1 = await db
190-
.selectFrom('person')
191-
.innerJoin('pet', 'pet.owner_id', 'person.id')
192-
.select((eb) => ['first_name', eb.fn.toJson('pet').as('pet')])
223+
.selectFrom('pet')
224+
.innerJoin('person', 'pet.owner_id', 'person.id')
225+
.select((eb) => ['name', eb.fn.toJson('person').as('person')])
193226
.execute()
194227

195228
expectType<
196229
{
197-
first_name: string
198-
pet: Selectable<Pet>
230+
name: string
231+
person: {
232+
id: number
233+
first_name: string
234+
last_name: string | null
235+
age: number
236+
gender: 'male' | 'female' | 'other'
237+
marital_status: 'single' | 'married' | 'divorced' | 'widowed' | null
238+
modified_at: string
239+
deleted_at: string | null
240+
}
199241
}[]
200242
>(r1)
201243
}

0 commit comments

Comments
 (0)