@@ -7,6 +7,68 @@ import type { Ref } from "./types.js"
7
7
// Helper type for any expression-like value
8
8
type ExpressionLike = BasicExpression | RefProxy < any > | Ref < any > | any
9
9
10
+ // Helper type to extract the underlying type from various expression types
11
+ type ExtractType < T > =
12
+ T extends RefProxy < infer U > ? U
13
+ : T extends Ref < infer U > ? U
14
+ : T extends BasicExpression < infer U > ? U
15
+ : T extends undefined ? undefined
16
+ : T extends null ? null
17
+ : T
18
+
19
+ // Helper type to determine aggregate return type based on input nullability
20
+ type AggregateReturnType < T > = ExtractType < T > extends infer U
21
+ ? U extends number | undefined | null
22
+ ? Aggregate < U >
23
+ : U extends number
24
+ ? Aggregate < number >
25
+ : Aggregate < number | undefined | null >
26
+ : Aggregate < number | undefined | null >
27
+
28
+ // Helper type to determine string function return type based on input nullability
29
+ type StringFunctionReturnType < T > = ExtractType < T > extends infer U
30
+ ? U extends string | undefined | null
31
+ ? BasicExpression < U >
32
+ : U extends string
33
+ ? BasicExpression < string >
34
+ : BasicExpression < string | undefined | null >
35
+ : BasicExpression < string | undefined | null >
36
+
37
+ // Helper type to determine numeric function return type based on input nullability
38
+ type NumericFunctionReturnType < T > = ExtractType < T > extends infer U
39
+ ? U extends number | undefined | null
40
+ ? BasicExpression < U >
41
+ : U extends number
42
+ ? BasicExpression < number >
43
+ : BasicExpression < number | undefined | null >
44
+ : BasicExpression < number | undefined | null >
45
+
46
+ // Helper type for binary numeric operations (combines nullability of both operands)
47
+ type BinaryNumericReturnType < T1 , T2 > =
48
+ ExtractType < T1 > extends infer U1
49
+ ? ExtractType < T2 > extends infer U2
50
+ ? U1 extends number
51
+ ? U2 extends number
52
+ ? BasicExpression < number >
53
+ : U2 extends number | undefined
54
+ ? BasicExpression < number | undefined >
55
+ : U2 extends number | null
56
+ ? BasicExpression < number | null >
57
+ : BasicExpression < number | undefined | null >
58
+ : U1 extends number | undefined
59
+ ? U2 extends number
60
+ ? BasicExpression < number | undefined >
61
+ : U2 extends number | undefined
62
+ ? BasicExpression < number | undefined >
63
+ : BasicExpression < number | undefined | null >
64
+ : U1 extends number | null
65
+ ? U2 extends number
66
+ ? BasicExpression < number | null >
67
+ : BasicExpression < number | undefined | null >
68
+ : BasicExpression < number | undefined | null >
69
+ : BasicExpression < number | undefined | null >
70
+ : BasicExpression < number | undefined | null >
71
+
10
72
// Operators
11
73
12
74
export function eq < T > (
@@ -207,67 +269,16 @@ export function ilike(
207
269
208
270
// Functions
209
271
210
- export function upper (
211
- arg :
212
- | RefProxy < string >
213
- | RefProxy < string | undefined >
214
- | RefProxy < string | null >
215
- | Ref < string >
216
- | Ref < string | undefined >
217
- | Ref < string | null >
218
- | string
219
- | string | undefined
220
- | string | null
221
- | BasicExpression < string >
222
- | BasicExpression < string | undefined >
223
- | BasicExpression < string | null >
224
- | undefined
225
- | null
226
- ) : BasicExpression < string | undefined | null > {
227
- return new Func ( `upper` , [ toExpression ( arg ) ] )
272
+ export function upper < T extends ExpressionLike > ( arg : T ) : StringFunctionReturnType < T > {
273
+ return new Func ( `upper` , [ toExpression ( arg ) ] ) as StringFunctionReturnType < T >
228
274
}
229
275
230
- export function lower (
231
- arg :
232
- | RefProxy < string >
233
- | RefProxy < string | undefined >
234
- | RefProxy < string | null >
235
- | string
236
- | string | undefined
237
- | string | null
238
- | BasicExpression < string >
239
- | BasicExpression < string | undefined >
240
- | BasicExpression < string | null >
241
- | undefined
242
- | null
243
- ) : BasicExpression < string | undefined | null > {
244
- return new Func ( `lower` , [ toExpression ( arg ) ] )
276
+ export function lower < T extends ExpressionLike > ( arg : T ) : StringFunctionReturnType < T > {
277
+ return new Func ( `lower` , [ toExpression ( arg ) ] ) as StringFunctionReturnType < T >
245
278
}
246
279
247
- export function length (
248
- arg :
249
- | RefProxy < string >
250
- | RefProxy < string | undefined >
251
- | RefProxy < string | null >
252
- | RefProxy < Array < any > >
253
- | RefProxy < Array < any > | undefined >
254
- | RefProxy < Array < any > | null >
255
- | string
256
- | string | undefined
257
- | string | null
258
- | Array < any >
259
- | Array < any > | undefined
260
- | Array < any > | null
261
- | BasicExpression < string >
262
- | BasicExpression < string | undefined >
263
- | BasicExpression < string | null >
264
- | BasicExpression < Array < any > >
265
- | BasicExpression < Array < any > | undefined >
266
- | BasicExpression < Array < any > | null >
267
- | undefined
268
- | null
269
- ) : BasicExpression < number | undefined | null > {
270
- return new Func ( `length` , [ toExpression ( arg ) ] )
280
+ export function length < T extends ExpressionLike > ( arg : T ) : NumericFunctionReturnType < T > {
281
+ return new Func ( `length` , [ toExpression ( arg ) ] ) as NumericFunctionReturnType < T >
271
282
}
272
283
273
284
export function concat (
@@ -286,33 +297,11 @@ export function coalesce(...args: Array<ExpressionLike>): BasicExpression<any> {
286
297
)
287
298
}
288
299
289
- export function add (
290
- left :
291
- | RefProxy < number >
292
- | RefProxy < number | undefined >
293
- | RefProxy < number | null >
294
- | number
295
- | number | undefined
296
- | number | null
297
- | BasicExpression < number >
298
- | BasicExpression < number | undefined >
299
- | BasicExpression < number | null >
300
- | undefined
301
- | null ,
302
- right :
303
- | RefProxy < number >
304
- | RefProxy < number | undefined >
305
- | RefProxy < number | null >
306
- | number
307
- | number | undefined
308
- | number | null
309
- | BasicExpression < number >
310
- | BasicExpression < number | undefined >
311
- | BasicExpression < number | null >
312
- | undefined
313
- | null
314
- ) : BasicExpression < number | undefined | null > {
315
- return new Func ( `add` , [ toExpression ( left ) , toExpression ( right ) ] )
300
+ export function add < T1 extends ExpressionLike , T2 extends ExpressionLike > (
301
+ left : T1 ,
302
+ right : T2
303
+ ) : BinaryNumericReturnType < T1 , T2 > {
304
+ return new Func ( `add` , [ toExpression ( left ) , toExpression ( right ) ] ) as BinaryNumericReturnType < T1 , T2 >
316
305
}
317
306
318
307
// Aggregates
@@ -321,72 +310,20 @@ export function count(arg: ExpressionLike): Aggregate<number> {
321
310
return new Aggregate ( `count` , [ toExpression ( arg ) ] )
322
311
}
323
312
324
- export function avg (
325
- arg :
326
- | RefProxy < number >
327
- | RefProxy < number | undefined >
328
- | RefProxy < number | null >
329
- | number
330
- | number | undefined
331
- | number | null
332
- | BasicExpression < number >
333
- | BasicExpression < number | undefined >
334
- | BasicExpression < number | null >
335
- | undefined
336
- | null
337
- ) : Aggregate < number | undefined | null > {
338
- return new Aggregate ( `avg` , [ toExpression ( arg ) ] )
313
+ export function avg < T extends ExpressionLike > ( arg : T ) : AggregateReturnType < T > {
314
+ return new Aggregate ( `avg` , [ toExpression ( arg ) ] ) as AggregateReturnType < T >
339
315
}
340
316
341
- export function sum (
342
- arg :
343
- | RefProxy < number >
344
- | RefProxy < number | undefined >
345
- | RefProxy < number | null >
346
- | number
347
- | number | undefined
348
- | number | null
349
- | BasicExpression < number >
350
- | BasicExpression < number | undefined >
351
- | BasicExpression < number | null >
352
- | undefined
353
- | null
354
- ) : Aggregate < number | undefined | null > {
355
- return new Aggregate ( `sum` , [ toExpression ( arg ) ] )
317
+ export function sum < T extends ExpressionLike > ( arg : T ) : AggregateReturnType < T > {
318
+ return new Aggregate ( `sum` , [ toExpression ( arg ) ] ) as AggregateReturnType < T >
356
319
}
357
320
358
- export function min (
359
- arg :
360
- | RefProxy < number >
361
- | RefProxy < number | undefined >
362
- | RefProxy < number | null >
363
- | number
364
- | number | undefined
365
- | number | null
366
- | BasicExpression < number >
367
- | BasicExpression < number | undefined >
368
- | BasicExpression < number | null >
369
- | undefined
370
- | null
371
- ) : Aggregate < number | undefined | null > {
372
- return new Aggregate ( `min` , [ toExpression ( arg ) ] )
321
+ export function min < T extends ExpressionLike > ( arg : T ) : AggregateReturnType < T > {
322
+ return new Aggregate ( `min` , [ toExpression ( arg ) ] ) as AggregateReturnType < T >
373
323
}
374
324
375
- export function max (
376
- arg :
377
- | RefProxy < number >
378
- | RefProxy < number | undefined >
379
- | RefProxy < number | null >
380
- | number
381
- | number | undefined
382
- | number | null
383
- | BasicExpression < number >
384
- | BasicExpression < number | undefined >
385
- | BasicExpression < number | null >
386
- | undefined
387
- | null
388
- ) : Aggregate < number | undefined | null > {
389
- return new Aggregate ( `max` , [ toExpression ( arg ) ] )
325
+ export function max < T extends ExpressionLike > ( arg : T ) : AggregateReturnType < T > {
326
+ return new Aggregate ( `max` , [ toExpression ( arg ) ] ) as AggregateReturnType < T >
390
327
}
391
328
392
329
/**
0 commit comments