typescriptpostgresqldrizzle

Get table name from a PGTable


I am starting out a new project with Drizzle ORM. Starting out with some assumptions:

Since I can make these assumptions, I thought I could significantly reduce the amount of boilerplate required for specifying foreign keys:

import {
  type PgColumn,
  type PgTableWithColumns,
  pgTableCreator,
  serial,
} from "drizzle-orm/pg-core";

import { camelCase, snakeCase } from "lodash";

export const pgTable = pgTableCreator((name) => {
  return `some-app_${name}`;
});

export function id() {
  return serial("id").primaryKey();
}

type TableWithId = PgTableWithColumns<{
  name: string;
  schema: string | undefined;
  dialect: "pg";
  columns: {
    id: PgColumn;
  };
}>;

export function fk(...relations: (TableWithId | TableWithId[])[]) {
  return Object.fromEntries(
    relations.flatMap((entry) => {
      const isOptional = Array.isArray(entry);
      const tables = isOptional ? entry : [entry];

      return tables.map((table) => {
        const columnName = `${snakeCase(`)}_id`;
        const propertyName = `${camelCase(table._.name)}Id`;
        const column = bigint(columnName, { mode: "number" }).references(() => {
          return table.id;
        });

        return [propertyName, isOptional ? column : column.notNull()];
      });
    }),
  );
}

This code is intended to be used as such:

export const contact = pgTable("contacts", {
  id: id(),
  firstName: varchar("first_name", { length: 128 }).notNull(),
  lastName: varchar("last_name", { length: 128 }).notNull(),
  ...fk(phone, [email], [address]),
  ...timestamps(),
});

Here a relation to the phone and email tables are mandatory (not null), but the relation to the email and address are optional.

The issue arises with accessing the name for a given PgTable. When I inspect the type of contact in my editor I see that they are type hinted with PgTableWithColumns. Which is what I used in the type hint to the fk function.

As a result as far as Typescript is concerned the function is correct. However when I run the code, I get the error:

TypeError: Cannot read properties of undefined (reading 'name')

This is referring to the expression: table._.name. When I log out table, I see that it does not match the type. The underscore property is infact missing, but the name provided to the table is present in a symbol key Symbol(drizzle:BaseName).

However, I am not sure how to access this property as I have not been able to import the symbol from anywhere.

It seems like the types for this package are broken and I might end up filing a bug with drizzle. But I kind of want to get this to work.

Any ideas?


Solution

  • How about getTableName?

    import { getTableName } from "drizzle-orm";
    const tableName = getTableName(table);