Transaction Type

Is there a type to use for passing a transaction into a function? I would like to do something like
await db.transaction(async (tx) => insertUser(tx, form.data))
await db.transaction(async (tx) => insertUser(tx, form.data))
but the type of tx is super long and not convenient at all.
13 Replies
Gabriel
Gabriel3mo ago
recent update changed the types and now I cant fit a Drizzle Transaction type into a normal Drizzle type. I'm not sure how aware the team is about it
Jakesdoc
JakesdocOP3mo ago
Yea I used to be able to just do typeof db and that was good enough but now the new update has changed the types. It doesn't seem there has ever been a proper way to represent that type, just work arounds.
Dave
Dave3mo ago
did you guys ever find a solution?
szeth
szeth3mo ago
type DB = NodePgDatabase<Schema>;

// option 1. extract it from the db object itself
type ExtractTQuery<T> = T extends PgDatabase<infer TQueryResult, infer Schema>
? [TQueryResult, Schema] : never;
type Transaction<T> = PgTransaction<ExtractTQuery<T>[0], ExtractTQuery<T>[1],
ExtractTablesWithRelations<ExtractTQuery<T>[1]>>;

type TX = Transaction<App.DB>;

// option 2 (extract it from the transaction method)
type TX = Parameters<DB[' transaction']>[0] extends (tx: infer T) => Promise<unknown>
? T: never
type DB = NodePgDatabase<Schema>;

// option 1. extract it from the db object itself
type ExtractTQuery<T> = T extends PgDatabase<infer TQueryResult, infer Schema>
? [TQueryResult, Schema] : never;
type Transaction<T> = PgTransaction<ExtractTQuery<T>[0], ExtractTQuery<T>[1],
ExtractTablesWithRelations<ExtractTQuery<T>[1]>>;

type TX = Transaction<App.DB>;

// option 2 (extract it from the transaction method)
type TX = Parameters<DB[' transaction']>[0] extends (tx: infer T) => Promise<unknown>
? T: never
i had this same problem today, solved it this way i personally prefer option 1 since getting it from the params seems a bit janky (im on mobile so excuse the formatting and typos)
Jakesdoc
JakesdocOP3mo ago
While this does work for me, it's obviously not how we should be getting the type. It seems crazy to me that this isn't something exposed by the library. Is it really that uncommon to need the type of a transaction? Do you know if they are planning on adding this at any point to the library itself?
szeth
szeth3mo ago
i completely agree, i looked through the source code to see if such a type was exposed but nopes that’s why i had to use these helpers but yeah not ideal
Jakesdoc
JakesdocOP3mo ago
Plus, who knows if either of these will work after the next update.
szeth
szeth3mo ago
and i dont work for drizzle so idk if it’s planned option 2 will, it just takes the return type. it’s just ugly option 1 should, since i’m just creating the PgTransaction type the same way it’s done internally in drizzle
Jakesdoc
JakesdocOP3mo ago
Well, hopefully they just expose an actual type in the future. For now though your solution works, so thank you lol
outranker
outranker3d ago
does anyone know if it has been exposed by the team or if there is an issue created for this?
AlexDaniel
AlexDaniel3d ago
I use this:
export type MyTransaction = //
typeof myDb.drizzle.transaction extends (
// eslint-disable-next-line @typescript-eslint/no-explicit-any -- this is fine, we don't care about that type
callback: (tx: infer T) => any
// eslint-disable-next-line @typescript-eslint/no-explicit-any -- this is fine, we don't care about that type
) => any
? T
: never;
export type MyTransaction = //
typeof myDb.drizzle.transaction extends (
// eslint-disable-next-line @typescript-eslint/no-explicit-any -- this is fine, we don't care about that type
callback: (tx: infer T) => any
// eslint-disable-next-line @typescript-eslint/no-explicit-any -- this is fine, we don't care about that type
) => any
? T
: never;
It seems to work. I think I'm using drizzle-orm 0.38.0. But it's awkward. basically, the trick is to use typeof db.transaction
Mario564
Mario5643d ago
Here's the proper way to type db and tx:
import type { YourDriverDatabase, YourDriverQueryResultHKT } from 'drizzle-orm/your-driver';
import type { DialectTransaction } from 'drizzle-orm/dialect-core';

export type Db = YourDriverDatabase;
export type Tx = DialectTransaction<YourDriverQueryResultHKT>;
import type { YourDriverDatabase, YourDriverQueryResultHKT } from 'drizzle-orm/your-driver';
import type { DialectTransaction } from 'drizzle-orm/dialect-core';

export type Db = YourDriverDatabase;
export type Tx = DialectTransaction<YourDriverQueryResultHKT>;
The above would look like this for PG with the postgres.js driver (just to give an example):
import type { PgTransaction } from 'drizzle-orm/pg-core';
import type { PostgresJsDatabase, PostgresJsQueryResultHKT } from 'drizzle-orm/postgres-js';

export type Db = PostgresJsDatabase;
export type Tx = PgTransaction<PostgresJsQueryResultHKT>;
import type { PgTransaction } from 'drizzle-orm/pg-core';
import type { PostgresJsDatabase, PostgresJsQueryResultHKT } from 'drizzle-orm/postgres-js';

export type Db = PostgresJsDatabase;
export type Tx = PgTransaction<PostgresJsQueryResultHKT>;
outranker
outranker3d ago
thanks for the reply. I am using postgres as a db. what driver does drizzle use by default? is it pg or postgres or postgres.js? thanks for the reply. it never occurred to me i could use typeof db.transaction
Want results from more Discord servers?
Add your server