DiamondDragon
DiamondDragon4w ago

Handling Upserts with Optional System Fields

Not sure if this is the best practice here but didn't appear there's a way of getting the Id field to be optional so it can be passed in for upserts (if it doesn't exist, insert, if it does patch). Not sure if my types are entirely correct but seems to work but happy to hear if anyone else agrees
function upsertDeal(ctx: MutationCtx, args: MakeIdOptional<Deals>) {
if (args._id) { // type _id = string & {} | undefined
return ctx.db.patch(args._id, args)
}

return insertDeal(ctx, args)
}


// Make only _id optional and exclude _creationTime for upserts
export type MakeIdOptional<T> = Omit<T, '_id' | '_creationTime'> & {
_id?: T extends { _id: Id<any> } ? Id<any> : never
}
function upsertDeal(ctx: MutationCtx, args: MakeIdOptional<Deals>) {
if (args._id) { // type _id = string & {} | undefined
return ctx.db.patch(args._id, args)
}

return insertDeal(ctx, args)
}


// Make only _id optional and exclude _creationTime for upserts
export type MakeIdOptional<T> = Omit<T, '_id' | '_creationTime'> & {
_id?: T extends { _id: Id<any> } ? Id<any> : never
}
2 Replies
deen
deen4w ago
convex/server exports WithoutSystemFields and WithOptionalSystemFields, I'm not sure if they're actually documented anywhere. but customising the types yourself like what you're doing is fine, if they work for you
DiamondDragon
DiamondDragonOP4w ago
oh didn't know about WithOptionalSystemFields, good shout out. thanks.

Did you find this page helpful?