Skip to content

Commit 3c4e90a

Browse files
authored
Fix sql function overload type inference (porsager#294)
fixes porsager#283
1 parent 50762d4 commit 3c4e90a

File tree

1 file changed

+53
-31
lines changed

1 file changed

+53
-31
lines changed

types/index.d.ts

+53-31
Original file line numberDiff line numberDiff line change
@@ -151,6 +151,44 @@ type UnwrapPromiseArray<T> = T extends any[] ? {
151151
[k in keyof T]: T[k] extends Promise<infer R> ? R : T[k]
152152
} : T;
153153

154+
type Keys = string
155+
156+
type SerializableObject<T, K extends any[]> =
157+
number extends K['length'] ? {} :
158+
Record<Keys & (keyof T) & (K['length'] extends 0 ? string : K[number]), postgres.SerializableParameter>
159+
160+
type First<T, K extends any[]> =
161+
// Tagged template string call
162+
T extends TemplateStringsArray ? TemplateStringsArray :
163+
// Identifiers helper
164+
T extends string ? string :
165+
// Dynamic values helper (depth 2)
166+
T extends readonly any[][] ? postgres.EscapableArray[] :
167+
// Insert/update helper (depth 2)
168+
T extends (object & infer R)[] ? SerializableObject<R, K>[] :
169+
// Dynamic values helper (depth 1)
170+
T extends readonly any[] ? postgres.EscapableArray :
171+
// Insert/update helper (depth 1)
172+
T extends object ? SerializableObject<T, K> :
173+
// Unexpected type
174+
never
175+
176+
type Rest<T> =
177+
T extends TemplateStringsArray ? never : // force fallback to the tagged template function overload
178+
T extends string ? string[] :
179+
T extends readonly any[][] ? [] :
180+
T extends (object & infer R)[] ? (Keys & keyof R)[] :
181+
T extends readonly any[] ? [] :
182+
T extends object ? (Keys & keyof T)[] :
183+
any
184+
185+
type Return<T, K extends any[]> =
186+
[T] extends [TemplateStringsArray] ?
187+
[unknown] extends [T] ? postgres.Helper<T, K> : // ensure no `PendingQuery` with `any` types
188+
[TemplateStringsArray] extends [T] ? postgres.PendingQuery<postgres.Row[]> :
189+
postgres.Helper<T, K> :
190+
postgres.Helper<T, K>
191+
154192
declare namespace postgres {
155193
class PostgresError extends Error {
156194
name: 'PostgresError';
@@ -408,30 +446,23 @@ declare namespace postgres {
408446
size(): Promise<[{ position: bigint, size: bigint }]>;
409447
}
410448

411-
type Serializable = null
449+
type EscapableArray = (string | number)[]
450+
451+
type Serializable = never
452+
| null
412453
| boolean
413454
| number
414455
| string
415456
| Date
416457
| Uint8Array;
417458

418-
type SerializableParameter = Serializable
459+
type SerializableParameter = never
460+
| Serializable
419461
| Helper<any>
420462
| Parameter<any>
421463
| ArrayParameter
422-
| Record<string, any> // implicit JSON
423464
| readonly SerializableParameter[];
424465

425-
type HelperSerializable = { [index: string]: SerializableParameter } | { [index: string]: SerializableParameter }[];
426-
427-
type SerializableKeys<T> = (keyof T) extends infer R
428-
? R extends keyof T
429-
? T[R] extends SerializableParameter
430-
? R
431-
: never
432-
: keyof T
433-
: keyof T;
434-
435466
interface Row {
436467
[column: string]: any;
437468
}
@@ -526,30 +557,21 @@ declare namespace postgres {
526557
}
527558

528559
interface Sql<TTypes extends JSToPostgresTypeMap> {
560+
/**
561+
* Query helper
562+
* @param first Define how the helper behave
563+
* @param rest Other optional arguments, depending on the helper type
564+
* @returns An helper object usable as tagged template parameter in sql queries
565+
*/
566+
<T, K extends Rest<T>>(first: T & First<T, K>, ...rest: K): Return<T, K>;
529567

530568
/**
531569
* Execute the SQL query passed as a template string. Can only be used as template string tag.
532570
* @param template The template generated from the template string
533-
* @param args Interpoled values of the template string
571+
* @param parameters Interpoled values of the template string
534572
* @returns A promise resolving to the result of your query
535573
*/
536-
<T extends readonly any[] = Row[]>(template: TemplateStringsArray, ...args: SerializableParameter[]): PendingQuery<AsRowList<T>>;
537-
538-
/**
539-
* Escape column names
540-
* @param columns Columns to escape
541-
* @returns A formated representation of the column names
542-
*/
543-
(columns: string[]): Helper<string>;
544-
(...columns: string[]): Helper<string>;
545-
546-
/**
547-
* Extract properties from an object or from an array of objects
548-
* @param objOrArray An object or an array of objects to extract properties from
549-
* @param keys Keys to extract from the object or from objets inside the array
550-
* @returns A formated representation of the parameter
551-
*/
552-
<T extends object | readonly object[], U extends SerializableKeys<T extends readonly object[] ? T[number] : T>>(objOrArray: T, ...keys: U[]): Helper<T, U[]>;
574+
<T extends readonly any[] = Row[]>(template: TemplateStringsArray, ...parameters: (SerializableParameter | PendingQuery<any>)[]): PendingQuery<AsRowList<T>>;
553575

554576
CLOSE: {};
555577
END: this['CLOSE'];

0 commit comments

Comments
 (0)