-
I'm trying to encapsulate some logic into a function like so: function doThings(sql: Sql<??>): ... {
...
} However, I don't know what to put instead of function doThings<TTypes extends extends { [name: string]: unknown }>(sql: Sql<TTypes>): ... {
...
} It also adds noise to what should be a straightforward definition, and seems to concern itself with implementation details of the Does anyone know if there's a better way and if I'm missing something important? Alternatively, what do we think about exporting the constraints on |
Beta Was this translation helpful? Give feedback.
Replies: 1 comment 1 reply
-
// no custom types
function doThings0(sql: postgres.Sql<{}>) {
sql`${1n}` // error: `1n` not assignable to `SerializableParameter<never>`
}
// with custom types
function doThings1(sql: postgres.Sql<{ bigint: bigint }>) {
sql`${1n}` // ok
sql`${sql.typed.bigint(1n)}` // ok
sql`${sql.typed.notfound(() => { throw 'wut'; })}` // error: `notfound` doesn't exists on `{ bigint: (value: bigint) => Parameter<bigint> }`
sql`${() => { throw 'wut'; }}` // error: `() => never` not assignable to `SerializableParameter<bigint>`
}
// disabling parameters validation entirely
function doThings2(sql: postgres.Sql<any>) {
sql`${1n}` // ok
sql`${sql.typed.bigint(1n)}` // ok
sql`${sql.typed.notfound(() => { throw 'wut'; })}` // ok
sql`${() => { throw 'wut'; }}` // ok
} Anyway, I don't think you need to make If you want to get accepted parameters types for a specific instance of async function select<
T extends {}, // custom types supported by the user-provided `Sql<T>`
U extends postgres.SerializableParameter<T[keyof T]> // parameters types supported by `postgres` (the `<T[keyof T]>` part is optional but adds support for user-defined custom types)
>(
sql: postgres.Sql<T>,
value: U
) {
const results = await sql<[{ value: U }]>`SELECT ${value} AS value`
return results[0].value // `select` returns `Promise<U>` then
}
const sql = postgres({
types: {
BigInt: postgres.BigInt
}
})
const bigints: bigint = await select(sql, 42n) // ok: `select(sql, 42n)` return `Promise<bigint>` I hope it helped you 👍 I agree types might look strange in |
Beta Was this translation helpful? Give feedback.
TTypes
is intended to pass custom types information to thesql
tagged template string, in order to provide rich completion for parameters (e.g.sql`SELECT ${1n}`;
only works if thepostgres.BigInt
custom type is passed to thepostgres()
function; the same apply to any user-defined custom types). WithoutTTypes
, it wouldn't be possible to validate parameters correctly (usingany
everywhere), and thus not possible neither to validate different helpers formats (because of conflicting function signatures), resulting in a type definition liketype Sql = (...args: any) => any
, which is quite useless...TTypes
just map custom types names to the value they accept/provide, so in your case, you cas…