Reputation: 11009
I am trying to wrap a Drizzle Query call into a reusable function that adds a little bit of an authorization layer on top of the database access. Here's an example:
async function loadMyThing(user: User, id: ThingId, opts?: Parameters<typeof db.query.myThings.findFirst>[0]) {
return db.query.myThings.findFirst({
...opts,
where: (t, {and, eq}) => and(eq(t.owner, user.id), eq(t.id, id)),
});
}
The problem I have is that loadMyThing looses signifcant amounts of typing with this. The returned result still is of a myThings row type, but I pass in e.g. columns
or with
, those options are not correctly reflected on the return value type:
const thing = await loadMyThing(me, thingId, { with: { thingRelation: true } });
// E: Property thingRelation does not exist on thing
thing!.thingRelation
thingRelation
obviously is a valid relation on the myThings table. Calling db.query.myThings.findFirst
directlygives the correctly typed result.
How can I "forward" typing information correctly here?
I tried some simple approaches using generics, but that didn't work. E.g.:
async function loadMyThing<T extends Parameters<typeof db.query.myThings.findFirst>[0]>(user: User, id: ThingId, opts?: T) {
return db.query.myThings.findFirst({
...opts,
where: (t, {and, eq}) => and(eq(t.owner, user.id), eq(t.id, id)),
});
}
I'm afraid my typescript foo is not strong enough to figure this out.
Upvotes: 1
Views: 39