Generic base repository abstract class
So, I’m trying to create a base repository class to extend based on my schema definitions, thing is I’m having trouble getting the types to work, here is my example
import type { InferSelectModel, SQL } from 'drizzle-orm';
import type { AnyPgTable } from 'drizzle-orm/pg-core';
import type { DB, DBTransaction } from './client';
export interface RepositoryOptions {
db?: DB;
tx?: DBTransaction;
}
/**
* A generic base repository class for Drizzle ORM
*
* Note: This implementation uses type assertions in some places to work
* around limitations in TypeScript's ability to fully type the Drizzle ORM.
* The public API is fully typed, but internal implementations may use 'any'.
*/
export class BaseRepository<
TTable extends AnyPgTable,
TSelect = InferSelectModel<TTable>,
> {
protected table: TTable;
protected db: DB | DBTransaction;
constructor(table: TTable, db: DB | DBTransaction) {
this.table = table;
this.db = db;
}
/**
* Find all records matching the given criteria
*/
async findAll(
options: {
limit?: number;
offset?: number;
orderBy?: SQL<unknown>;
where?: SQL<unknown>;
} = {},
): Promise<TSelect[]> {
const { limit, offset, orderBy, where } = options;
// Using any to avoid complex type issues with the query builder
let query = this.db.select().from(this.table).$dynamic();
if (where) {
query = query.where(where);
}
if (orderBy) {
query = query.orderBy(orderBy);
}
if (limit) {
query = query.limit(limit);
}
if (offset) {
query = query.offset(offset);
}
return query;
}
}
import type { InferSelectModel, SQL } from 'drizzle-orm';
import type { AnyPgTable } from 'drizzle-orm/pg-core';
import type { DB, DBTransaction } from './client';
export interface RepositoryOptions {
db?: DB;
tx?: DBTransaction;
}
/**
* A generic base repository class for Drizzle ORM
*
* Note: This implementation uses type assertions in some places to work
* around limitations in TypeScript's ability to fully type the Drizzle ORM.
* The public API is fully typed, but internal implementations may use 'any'.
*/
export class BaseRepository<
TTable extends AnyPgTable,
TSelect = InferSelectModel<TTable>,
> {
protected table: TTable;
protected db: DB | DBTransaction;
constructor(table: TTable, db: DB | DBTransaction) {
this.table = table;
this.db = db;
}
/**
* Find all records matching the given criteria
*/
async findAll(
options: {
limit?: number;
offset?: number;
orderBy?: SQL<unknown>;
where?: SQL<unknown>;
} = {},
): Promise<TSelect[]> {
const { limit, offset, orderBy, where } = options;
// Using any to avoid complex type issues with the query builder
let query = this.db.select().from(this.table).$dynamic();
if (where) {
query = query.where(where);
}
if (orderBy) {
query = query.orderBy(orderBy);
}
if (limit) {
query = query.limit(limit);
}
if (offset) {
query = query.offset(offset);
}
return query;
}
}
1 Reply
It looks like it should work but I get the following error in the
Also for reference, this is how I’m getting the DB and DBTransaction types
Any clues or examples on how to achieve this?
this.table
when creating the select
Argument of type 'TTable' is not assignable to parameter of type 'TableLikeHasEmptySelection<TTable> extends true ? DrizzleTypeError<"Cannot reference a data-modifying statement subquery if it doesn't contain a `returning` clause"> : TTable'.
Type 'PgTable<Required<{ schema: string | undefined; name: string; dialect: string; columns: Record<string, PgColumn<ColumnBaseConfig<ColumnDataType, string>, {}, {}>>; }>>' is not assignable to type 'TableLikeHasEmptySelection<TTable> extends true ? DrizzleTypeError<"Cannot reference a data-modifying statement subquery if it doesn't contain a `returning` clause"> : TTable'.
Argument of type 'TTable' is not assignable to parameter of type 'TableLikeHasEmptySelection<TTable> extends true ? DrizzleTypeError<"Cannot reference a data-modifying statement subquery if it doesn't contain a `returning` clause"> : TTable'.
Type 'PgTable<Required<{ schema: string | undefined; name: string; dialect: string; columns: Record<string, PgColumn<ColumnBaseConfig<ColumnDataType, string>, {}, {}>>; }>>' is not assignable to type 'TableLikeHasEmptySelection<TTable> extends true ? DrizzleTypeError<"Cannot reference a data-modifying statement subquery if it doesn't contain a `returning` clause"> : TTable'.
export const db = drizzle({
client: psClient,
schema,
casing: "snake_case",
});
export type DBTransaction = Parameters<Parameters<typeof db.transaction>[0]>[0];
export type DB = typeof db;
export const db = drizzle({
client: psClient,
schema,
casing: "snake_case",
});
export type DBTransaction = Parameters<Parameters<typeof db.transaction>[0]>[0];
export type DB = typeof db;