left join make the types never

Hi guys, im now sure if this is the expected behavior or not but i have this query
const reminders = await db.select({
reminderId: reminderTable.id,
})
.from(reminderTable);
const reminders = await db.select({
reminderId: reminderTable.id,
})
.from(reminderTable);
where the type of reminders is
const reminders: {
reminderId: number;
}[]
const reminders: {
reminderId: number;
}[]
so that is ok but when i add a left join all the types are never
const reminders = await db.select({
reminderId: reminderTable.id,
})
.from(reminderTable)
.leftJoin(sentReminderTable, eq(reminderTable.id, sentReminderTable.reminderId));
const reminders = await db.select({
reminderId: reminderTable.id,
})
.from(reminderTable)
.leftJoin(sentReminderTable, eq(reminderTable.id, sentReminderTable.reminderId));
this is the left join and now the types are
{
reminderId: never;
}[]
{
reminderId: never;
}[]
I'm not sure why is never i was expecting something like
{
reminderId: number | null;
}[]
{
reminderId: number | null;
}[]
Im doing something wrong or it is correct this way? Im using "drizzle-orm": "^0.29.2" Thanks so much in advance for the time
5 Replies
Angelelz
Angelelz12mo ago
This is not expected behavior. It's very likely there's an issue with your sentReminderTable
GabrielC
GabrielCOP12mo ago
i'm definding the table in this way
const baseMysqlTable = <TColumnsMap extends Record<string, MySqlColumnBuilder>>(name: string, columns: TColumnsMap) => {
return mysqlTable(name, {
id: int('id').primaryKey().autoincrement().notNull(),
updatedAt: timestamp('updated_at').onUpdateNow(),
createdAt: timestamp('created_at').defaultNow().notNull(),
deletedAt: timestamp('deleted_at'),
...columns,
});
};

export default baseMysqlTable;

export const sentReminderTable = baseMysqlTable('sent_reminder', {
reminderId: int('reminder_id').references(() => reminderTable.id).notNull(),
invoiceId: int('invoice_id').references(() => invoiceTable.id).notNull(),
notificationType: mysqlEnum('notification_type', reminderNotificationType).notNull(),
familyMemberId: int('family_member_id').references(() => familyMemberTable.id).notNull(),
sentAt: timestamp('sent_at').notNull(),
});
const baseMysqlTable = <TColumnsMap extends Record<string, MySqlColumnBuilder>>(name: string, columns: TColumnsMap) => {
return mysqlTable(name, {
id: int('id').primaryKey().autoincrement().notNull(),
updatedAt: timestamp('updated_at').onUpdateNow(),
createdAt: timestamp('created_at').defaultNow().notNull(),
deletedAt: timestamp('deleted_at'),
...columns,
});
};

export default baseMysqlTable;

export const sentReminderTable = baseMysqlTable('sent_reminder', {
reminderId: int('reminder_id').references(() => reminderTable.id).notNull(),
invoiceId: int('invoice_id').references(() => invoiceTable.id).notNull(),
notificationType: mysqlEnum('notification_type', reminderNotificationType).notNull(),
familyMemberId: int('family_member_id').references(() => familyMemberTable.id).notNull(),
sentAt: timestamp('sent_at').notNull(),
});
i use this helper baseMysqlTable bc all my tables use this id, updatedAt, createdAt, etc but yes that helperls is the problem i see, if i dont use that it works but im not sure whhy bc im returnin a mysqlTable inside the function do you know how can i do this in another way? bc all my tables need this columns so in order to not write it in every table i did this a solution can be this
export const baseTableColumns = {
id: int('id').primaryKey().autoincrement().notNull(),
updatedAt: timestamp('updated_at').onUpdateNow(),
createdAt: timestamp('created_at').defaultNow().notNull(),
deletedAt: timestamp('deleted_at')
}

export const sentReminderTable = mysqlTable('sent_reminder', {
...baseTableColumns,
reminderId: int('reminder_id').references(() => reminderTable.id).notNull(),
invoiceId: int('invoice_id').references(() => invoiceTable.id).notNull(),
notificationType: mysqlEnum('notification_type', reminderNotificationType).notNull(),
familyMemberId: int('family_member_id').references(() => familyMemberTable.id).notNull(),
sentAt: timestamp('sent_at').notNull(),
});
export const baseTableColumns = {
id: int('id').primaryKey().autoincrement().notNull(),
updatedAt: timestamp('updated_at').onUpdateNow(),
createdAt: timestamp('created_at').defaultNow().notNull(),
deletedAt: timestamp('deleted_at')
}

export const sentReminderTable = mysqlTable('sent_reminder', {
...baseTableColumns,
reminderId: int('reminder_id').references(() => reminderTable.id).notNull(),
invoiceId: int('invoice_id').references(() => invoiceTable.id).notNull(),
notificationType: mysqlEnum('notification_type', reminderNotificationType).notNull(),
familyMemberId: int('family_member_id').references(() => familyMemberTable.id).notNull(),
sentAt: timestamp('sent_at').notNull(),
});
Angelelz
Angelelz12mo ago
Yes, I was going to suggest this. Did it work?
GabrielC
GabrielCOP12mo ago
Yes, that works perfect
ChocolateSauce
ChocolateSauce2mo ago
Hi, I'm having this exact same problem, but the workaround that the OP used isn't great for me because my wrapper does more than just add some columns. Is this behavior a bug that the team could consider fixing?
Want results from more Discord servers?
Add your server