Common Fields Logic For Multiple Tables
I have a set of tables inheriting the same set of columns:
I want to define a base class with common functionality for these two tables. It should look something like that:
How do I do so properly to avoid maximum of the TypeScript pain? So far can't figure out a clean solution.
3 Replies
I found out that it's probably not a good idea to share the same instance of a column definition e.g. don't do this
const shared_cols = { col1: integer(), col2: text(), }; const my_table = pgTable("some_table", { ...shared_cols });
because pgTable()
modifies those instances of the columns. So instead you should do function shared_cols() { return { col1: integer(), col2: text(), }; }
and here's one example of my usage of that:
Regarding the use of AnyPgColumn
- this has solved some TypeScript issues whereby the foreign key fields (created_by
, etc) were not being typed correctly due to the reference.
Also, using as const
I think helps TypeScript to know that the field types are stable and won't change.
Other than that, I use types like PgTable
and others when I have functions that must work with multiple tables:
e.g.
Oh yeah and casting the result is often, but not always, necessary in these types of functions e.g. as SelectResult<ReturnType<S>, "single", {}>[]
@JustWayne Thank you a ton! This helped a lot.
Not sure about
it's probably not a good idea to share the same instance of a column definitionOfficial drizzle docs recommend this approach. So far I didn't have any issues with it: https://orm.drizzle.team/docs/sql-schema-declaration Here's some code I ended up writing (SQLite):
Drizzle ORM - Schema
Drizzle ORM is a lightweight and performant TypeScript ORM with developer experience in mind.
Yeah, sorry I meant to say: For the style of declarations that I use wherein I don't supply the field name twice. E.g. My whole codebase is
field_name: text(), ...
instead of field_name: text("field_name"), ...
like you find in the docs - you can totally share your field declaration objects if you don't mind double-entering the field names. Otherwise, the object created by text()
will only retain the last field name that it was applied for.
That was actually a rule that I made for myself after observing the incorrect field names being applied in the meta-data structures when I was doing something like const some_table = pgTable("some_table", { xyz_field: shared.abc_field });
(which I don't do anymore anyway, because it causes the meta-data available from abc_field: text()
to have the field name xyz_field
)
However, that subtle difference led me to say "I'm probably better off not sharing the same field declaration object meta-data in general because you never know when it might bite you in the ayy"