DT
Drizzle Team•3mo ago
Simon

Drizzle with Zod throws type errors with simple `numeric` example

For example, I define a PostgreSQL table with an input schema:
export const Foo = pgTable('foo', {
bar: numeric('bar'),
});
export const CreateFooSchema = createInsertSchema(Foo);
export const Foo = pgTable('foo', {
bar: numeric('bar'),
});
export const CreateFooSchema = createInsertSchema(Foo);
When using this in my API:
create: protectedProcedure
.input(CreateFooSchema)
.mutation(({ ctx, input }) => {
return ctx.db.insert(Foo).values(input);
}),
create: protectedProcedure
.input(CreateFooSchema)
.mutation(({ ctx, input }) => {
return ctx.db.insert(Foo).values(input);
}),
I get a type error thrown:
Types of property 'bar' are incompatible.
Type 'string | null | undefined' is not assignable to type 'string | SQL<unknown> | Placeholder<string, any> | null'.
Types of property 'bar' are incompatible.
Type 'string | null | undefined' is not assignable to type 'string | SQL<unknown> | Placeholder<string, any> | null'.
This is specifically a problem with the numeric and decimal data types. Other standard data types work fine. Any ideas on a fix?
7 Replies
Simon
Simon•3mo ago
Bump
pacto
pacto•3mo ago
your numeric data can be null when you are grabbing it from db, you can either make it notNull in drizzle schema or nullable in zod to allow null values
Simon
Simon•3mo ago
@pacto shouldn't createInsertSchema infer the schema from the pgTable definition?
johtso
johtso•3mo ago
@Simon did you find a solution? I'm having the same problem with a custom Date datatype
const date = customType<
{ data: Date; driverData: string; }
>({
dataType() {
return 'text';
},
fromDriver(value: string): Date {
return new Date(value);
},
toDriver(value: Date): string {
if (value.getHours() !== 0 || value.getMinutes() !== 0 || value.getSeconds() !== 0 || value.getMilliseconds() !== 0) {
throw new Error('Date must have a time of 00:00:00.000');
}
try {
return value.toISOString().split('T')[0] as string;
} catch (e) {
console.log(`failed to covert ${JSON.stringify(value)} to iso string`)
throw e;
}
},
});
const date = customType<
{ data: Date; driverData: string; }
>({
dataType() {
return 'text';
},
fromDriver(value: string): Date {
return new Date(value);
},
toDriver(value: Date): string {
if (value.getHours() !== 0 || value.getMinutes() !== 0 || value.getSeconds() !== 0 || value.getMilliseconds() !== 0) {
throw new Error('Date must have a time of 00:00:00.000');
}
try {
return value.toISOString().split('T')[0] as string;
} catch (e) {
console.log(`failed to covert ${JSON.stringify(value)} to iso string`)
throw e;
}
},
});
export const emails = sqliteTable('emails', {
idempotencyKey: text('idempotency_key').primaryKey(),
membershipEndDate: date('membership_end_date')
});
export const emails = sqliteTable('emails', {
idempotencyKey: text('idempotency_key').primaryKey(),
membershipEndDate: date('membership_end_date')
});
export const insertEmailSchema = createInsertSchema(emails, {
timeSent: z.date(),
membershipEndDate: z.date(),
}).strict();
export type InsertEmail = z.infer<typeof insertEmailSchema>;
export const insertEmailSchema = createInsertSchema(emails, {
timeSent: z.date(),
membershipEndDate: z.date(),
}).strict();
export type InsertEmail = z.infer<typeof insertEmailSchema>;
export const createEmail = async (
db: dbType,
email: InsertEmail
): Promise<boolean> => {
const result = await db
.insert(emails)
.values(email)
return result.results.length > 0;
}
export const createEmail = async (
db: dbType,
email: InsertEmail
): Promise<boolean> => {
const result = await db
.insert(emails)
.values(email)
return result.results.length > 0;
}
Types of property 'membershipEndDate' are incompatible.
Type 'Date | null | undefined' is not assignable to type 'Date | SQL<unknown> | Placeholder<string, any> | null'.
Type 'undefined' is not assignable to type 'Date | SQL<unknown> | Placeholder<string, any> | null'.
Types of property 'membershipEndDate' are incompatible.
Type 'Date | null | undefined' is not assignable to type 'Date | SQL<unknown> | Placeholder<string, any> | null'.
Type 'undefined' is not assignable to type 'Date | SQL<unknown> | Placeholder<string, any> | null'.
ahh.. I think it's exactOptionalPropertyTypes in tsconfig
Simon
Simon•3mo ago
Yeah that is what was throwing the TypeError 🙃
Amos
Amos•2mo ago
Did you manage to fix it? I guess you are also using @effect/schema as I've seen you there too 😛 but they require that exactOptionalPropertyTypes I think?
johtso
johtso•2mo ago
I'm not really using effect schema with drizzle. I think I'm just not using the zod schema at all, instead just explicitly passing the relevant key/values as the values argument in my query..
Want results from more Discord servers?
Add your server