K
Kysely•10mo ago
virk

Need help improving a custom helper

My dopamine with Kysely is quite high right now, so I am experimenting all sorts of things to create custom helpers for common use-cases. Here's an example of a working demo https://old.kyse.link/?p=s&i=qkTHjgwIuyb847wjoRd3 Following is a trimmed snippet from the above mentioned demo, for which I need help.
function month<DB, TB extends keyof DB & string>(eb: ExpressionBuilder<DB, TB>, col: {
[K in keyof DB[TB]]: DB[TB][K] extends Date | { __select__: Date } ? K : never
}[keyof DB[TB]]) {
return sql<number>`EXTRACT(MONTH from ${sql.ref('created_at')}::date)`
}

const users = await db
.selectFrom('users')
.selectAll()
.where((eb) => {
return eb(month(eb, 'created_at'), '=', 11)
})
.select((eb) => {
return month(eb, 'created_at').as('creationMonth')
})
.executeTakeFirst()
function month<DB, TB extends keyof DB & string>(eb: ExpressionBuilder<DB, TB>, col: {
[K in keyof DB[TB]]: DB[TB][K] extends Date | { __select__: Date } ? K : never
}[keyof DB[TB]]) {
return sql<number>`EXTRACT(MONTH from ${sql.ref('created_at')}::date)`
}

const users = await db
.selectFrom('users')
.selectAll()
.where((eb) => {
return eb(month(eb, 'created_at'), '=', 11)
})
.select((eb) => {
return month(eb, 'created_at').as('creationMonth')
})
.executeTakeFirst()
Is it possible for me use the month helper without passing it the eb instance explicitly? I know for the most part the answer is NO. But still want to check my luck and see if there is something I am unaware of.
Solution:
Yeah unfortunately typescript doesn't bend that way. We wouldn't need the whole ExpressionBuilder callback thingy anywhere if it did. We could just use free functions and they'd somehow catch the context through generics in the return value. another option is month(eb)('created_at')....
Jump to solution
3 Replies
Igal
Igal•10mo ago
Hey 👋 So far, only possible while passing eb as argument. Anything I tried resulted in <never, unknown>
virk
virkOP•10mo ago
Yeah, I suspected that. I think passing eb explicitly is fine as well. Its just month('created_at') reads a little better than month(eb, 'created_at') Thanks a ton for looking into it 🙂
Solution
koskimas
koskimas•10mo ago
Yeah unfortunately typescript doesn't bend that way. We wouldn't need the whole ExpressionBuilder callback thingy anywhere if it did. We could just use free functions and they'd somehow catch the context through generics in the return value. another option is month(eb)('created_at').

Did you find this page helpful?