How to type a generic selection function

I've been trying to implement a generic select function but can't figure out how to type it Something like this:
async function select<T extends Something>(selectFields: T, limit: number): SomethingReturn> {
const db = await getClient()
const res = await db.select(selectFields).from(users).limit(limit)
return res
}

const users = await select({ name: users.name }, 10)
// Should be typed `{ name: string }[]`
async function select<T extends Something>(selectFields: T, limit: number): SomethingReturn> {
const db = await getClient()
const res = await db.select(selectFields).from(users).limit(limit)
return res
}

const users = await select({ name: users.name }, 10)
// Should be typed `{ name: string }[]`
What type should I use to replace Something and SomethingReturn I tried a combination of
type TSchema = ExtractTablesWithRelations<typeof schema>
type TFields = TSchema['users']['columns']
type TSchema = ExtractTablesWithRelations<typeof schema>
type TFields = TSchema['users']['columns']
and multiple combinations of PgSelect , PgSelectBase but can't get it to work properly Any help appreciated
11 Replies
Mario564
Mario5643mo ago
@alexb Use the SelectedFields type (T extends SelectedFields)
alexb
alexbOP3mo ago
@Mario564 thanks SelectedFields really help but I'm still having issues It works unless I add a where condition ie: return db.select(selectFields).from(users) // works return db.select(selectFields).from(users).where(eq(users.id, '1111')) // returns "any"
Mario564
Mario5643mo ago
Where is the SelectedFields being imported from? I'm looking at the source code and had forgotten there's one for each dialect, so you have to use the correct one for whatever dialect you're using
alexb
alexbOP3mo ago
from import type { SelectedFields } from 'drizzle-orm/pg-core'
Mario564
Mario5643mo ago
That should work Are you still explicitly defining the return type for the function?
alexb
alexbOP3mo ago
Nope, letting typescript infer it Attaching a more concrete example
No description
No description
Mario564
Mario5643mo ago
Couldn't find a clean solution to this problem, but I did come up with a workaround
async function select<T extends SelectedFields>(fields: T) {
const query = db.select(fields).from(users);
return await query.where(eq(users.id, 1)) as Awaited<typeof query>;
}
async function select<T extends SelectedFields>(fields: T) {
const query = db.select(fields).from(users);
return await query.where(eq(users.id, 1)) as Awaited<typeof query>;
}
alexb
alexbOP3mo ago
Nice thanks! yeah this is exactly the workaround I used
async function select<T extends SelectedFields>(selectFields: T) {
const drizzle = await getClient()
const query = drizzle.select(selectFields).from(users)
const queryWithWhere = query.where(eq(users.id, '123456')) as unknown as typeof query
const res = await queryWithWhere
return res
}
async function select<T extends SelectedFields>(selectFields: T) {
const drizzle = await getClient()
const query = drizzle.select(selectFields).from(users)
const queryWithWhere = query.where(eq(users.id, '123456')) as unknown as typeof query
const res = await queryWithWhere
return res
}
That'll do, I feel like this is a pretty standard use case though, surprised there's no clean way to do it :/
Mario564
Mario5643mo ago
There probably is but it's not documented anywhere at the moment The select types are also very complex so that certainly doesn't help
alexb
alexbOP3mo ago
Thanks for your help! I'll update the thread if I ever find a better solution
Mario564
Mario5643mo ago
Alright, glad to have helped!
Want results from more Discord servers?
Add your server