typescript - Hur säkerställer man typ-säker frågering med Drizzle ORM i en basrepositories hantering av primärnycklar?


Jag bygger en abstrakt basrepository-klass med Drizzle ORM för en PostgreSQL-databas. Repositoriet är generiskt och fungerar med vilken tabell som helst som utökar PgTable, och primärnyckeln skickas dynamiskt. Här är den relevanta delen av min implementation:

async findOne(id: T['$inferSelect'][ID]): Promise<InferSelectModel<T>> {
  if (!id) {
    throw new Error('ID is required');
  }

  const result = await this.db
    .select()
    .from(this.table)
    .where(eq(sql.raw(`${this.primaryKey.toString()}`), id));

  if (!result.length) {
    throw new Error(`No record found for ID: ${id}`);
  }

  return result[0];
}

Problemet:

Användningen av sql.raw($ {this.primaryKey.toString()}) är inte typ-säker, vilket motverkar syftet med att använda TypeScript för strikt typning. Om strängen primaryKey inte matchar det faktiska kolumnnamnet i tabellen kommer det endast att ge runtime-fel.

Jag vill ha en lösning som säkerställer att primärnyckeln är typ-säker och kan valideras korrekt vid kompileringsstid.

Ytterligare sammanhang:

  • Primärnyckelparametern i konstruktorn är av typen ID som utvidgar keyof T['$inferSelect'].
  • Förvaret används för att utföra vanliga CRUD-operationer (findOne, create, update, delete) för olika tabeller.
  • Drizzle ORM stöder inte direkt operationer som .where() med dynamiska nycklar utan sql.raw.

Här är konstruktorn för ytterligare referens:

constructor(
  protected readonly db: DrizzleDB,
  protected readonly table: T,
  protected readonly primaryKey: ID,
) {}
  1. Hur kan jag göra where()-klassen för primärnyckeln typ-säker i detta sammanhang?
  2. Finns det ett bättre tillvägagångssätt eller mönster för att hantera dynamiska primärnycklar i en repository-klass med Drizzle ORM?