drizzle-orm: [BUG]: Serial type in PostgreSQL not recognized as having a default value
What version of drizzle-orm are you using?
0.26.1
What version of drizzle-kit are you using?
0.18.1
Describe the Bug
I have encountered an issue with handling PostgreSQL’s serial types (smallserial, serial, and bigserial), it appears that Drizzle does not regard them as having default values, despite these types inherently including a default auto-incrementing behavior in PostgreSQL.
export const test = pgTable("test", {
id: smallserial('id').primaryKey(),
});
type NewTest = InferModel<typeof test, 'insert'>;
// The inferred type for 'id' is number, when it should be nullable as it has a default value
Expected behavior
In the above example, I’d expect the ‘id’ field to be inferred as nullable for inserts because smallserial inherently provides a default auto-incrementing value.
Environment & setup
No response
About this issue
- Original URL
- State: closed
- Created a year ago
- Reactions: 9
- Comments: 24
For those having issues getting the insert statement to correctly auto-generate the next number in the serial sequence, this worked for me:
Set your serial column value to
<table>.<column_name>.default.The id column I’m omitting here is of type
smallserialand since that field is not nullable in the typeInferModel<typeof table, 'insert'>, I can’t insert usingdb.insert(table).values(obj)without explicitly giving a value for the id which shouldn’t be required.Hey, I had the same error but with
serial. I found a very strange fix for it and I don’t know if it will work for everyone.This seems to work for me and the tables are correct. I’m not sure why this works, perhaps there is an issue with the code for generating the create table query, but not with the alter table query. This also seems to work with some other weird schema errors and I originally found this technique because I was having trouble with pushing composite keys.
I just investigated this. This is not an issue, I believe there are a couple misunderstandings here.
First of all, the issue under discussion is about the type that is inferred for the
serialfamily of database types. If you are running into migrations/drizzle-kit issues, those are not being tracked here.The second thing I see here is the confusion around
nullableandnullishandundefined:integer generated by default as identity not null. That means that it’s an auto incremented integer type that cannot be null.nullandundefined, although in JS both are kinda similar but not really, for drizzlenullis the literal null value that will be passed to the database and undefined mean nothing will be passed to the database so that the database can insert thedefaultvalue to that row.@rogden suggested a trick to pass
<table>.<column_name>.defaultto the values on insert, this just works by coincidence. This property is just a type convenience for the drizzle team and at runtime is actuallyundefined, so you might as well just not put <column_name> in the insert and you will get the same result.Third, it’s very important to point out that a serial column is a tricky one, you can omit it in the insert and get the next generated integer, you can insert any number you like including ones not unique (as long as it’s not a primary key), but you CANNOT insert a null value into it.
I encourage anyone to do some tests for yourself in an actual db:
Lastly, for the people having problems with migrations and push commands, the
serialtype have some weird behaviors. So it’s not drizzle’s fault. Check here if you want to know about it.Anyway, the types are working properly. I just did a couple type checks and they are all good:
I’ll close this issue as resolved, but feel free to reach out if you need to.
I’m not sure how anyone is getting
smallserialto even migrate. I’m immediately thrown this on push to db attemptsdespite
import { smallserial } from 'drizzle-orm/pg-core.The case is also the same with
serial.Is this some beginners error? Fairly new to typescript and drizzle.
Here’s an update,
InferModel<typeof table, 'insert'>is working correctly when I chenge my primary key, id, to be of typeserialrather thansmallserial. When I do this the inferred type correctly types the id field like soid? : number | undefined. When using the typesmallserial,InferModeldefines the id field withid : number, leading to the type error I was encountering.