Oscar
Oscar3mo ago

Redundant typing

Hey noob question here I have a table definition here :
//schema.ts
import { defineSchema, defineTable } from "convex/server";
import { v } from "convex/values";
import { authTables } from "@convex-dev/auth/server";

export default defineSchema({
...authTables,
users: defineTable({
name: v.string(),
email: v.string(),
phone: v.string(),
company: v.optional(v.string()),
createdAt: v.number(),
}).index("by_email", ["email"]),
orders: defineTable({
orderId: v.id("orders"),
clientEmail: v.string(),
price: v.number() ?? v.string(),
createdAt: v.number(),
}).index("by_user", ["orderId"]),
});
//schema.ts
import { defineSchema, defineTable } from "convex/server";
import { v } from "convex/values";
import { authTables } from "@convex-dev/auth/server";

export default defineSchema({
...authTables,
users: defineTable({
name: v.string(),
email: v.string(),
phone: v.string(),
company: v.optional(v.string()),
createdAt: v.number(),
}).index("by_email", ["email"]),
orders: defineTable({
orderId: v.id("orders"),
clientEmail: v.string(),
price: v.number() ?? v.string(),
createdAt: v.number(),
}).index("by_user", ["orderId"]),
});
as you can see, I define the type of price here. In another file :
//orderFunctions.ts
import { mutation, query } from "./_generated/server";
import { v } from "convex/values";

export const addOrder = mutation({
args: {
clientEmail: v.string(),
price: v.optional(v.string() ?? v.number()),
},
handler: async (ctx, args) => {
const userId = await ctx.db.insert("orders", {
clientEmail: args.clientEmail,
price: args.price ?? "no price given",
createdAt: Date.now() ?? "no date given",
});
return userId;
},
});

export const getOrders = query({
args: {},
handler: async (ctx) => {
return await ctx.db.query("orders").collect();
},
});
//orderFunctions.ts
import { mutation, query } from "./_generated/server";
import { v } from "convex/values";

export const addOrder = mutation({
args: {
clientEmail: v.string(),
price: v.optional(v.string() ?? v.number()),
},
handler: async (ctx, args) => {
const userId = await ctx.db.insert("orders", {
clientEmail: args.clientEmail,
price: args.price ?? "no price given",
createdAt: Date.now() ?? "no date given",
});
return userId;
},
});

export const getOrders = query({
args: {},
handler: async (ctx) => {
return await ctx.db.query("orders").collect();
},
});
As you can see I am also defining types of args here, and setting values accordingly in "insert" part. My question is : since I'm already defining types when doing the tables, can I use these types in the args ? so that I don't have to copy/paste types between table and args ?
8 Replies
Convex Bot
Convex Bot3mo ago
Thanks for posting in <#1088161997662724167>. Reminder: If you have a Convex Pro account, use the Convex Dashboard to file support tickets. - Provide context: What are you trying to achieve, what is the end-user interaction, what are you seeing? (full error message, command output, etc.) - Use search.convex.dev to search Docs, Stack, and Discord all at once. - Additionally, you can post your questions in the Convex Community's <#1228095053885476985> channel to receive a response from AI. - Avoid tagging staff unless specifically instructed. Thank you!
sleepless
sleepless3mo ago
There is schema.tables.whatever.validator.fields You could do something like
args: { foo: schema.tables.bar.validator.fields.foo },
args: { foo: schema.tables.bar.validator.fields.foo },
or if you want to take any of them (eg for upsert)
args: partial(schema.tables.bar.validator.fields),
args: partial(schema.tables.bar.validator.fields),
Here's a real example if it helps
// Action to update current user's profile data
export const updateCurrentUser = mutation({
args: omit(partial(schema.tables.users.validator.fields), protectedUserFields),
handler: async (ctx, updates) => {
const user = await requireCurrentUser(ctx);
await ctx.db.patch(user._id, {
...updates,
});
},
});
// Action to update current user's profile data
export const updateCurrentUser = mutation({
args: omit(partial(schema.tables.users.validator.fields), protectedUserFields),
handler: async (ctx, updates) => {
const user = await requireCurrentUser(ctx);
await ctx.db.patch(user._id, {
...updates,
});
},
});
Oscar
OscarOP3mo ago
I'm trying this but I think I'm mistaken is your schema the defineSchema from schema.ts ?
Oscar
OscarOP3mo ago
No description
Oscar
OscarOP3mo ago
but yeah since in Convex "everything is Typescript", I suppose what you are suggesting should work one way or another for my codebase
sleepless
sleepless3mo ago
from convex/schema.ts -> export default defineSchema({...}) then in other files like convex/auth.ts just import schema from "./schema";
djbalin
djbalin3mo ago
Argument Validation without Repetition
A few more advanced techniques & helpers to further reduce duplication and accelerate your Convex workflow.
npm
convex-helpers
A collection of useful code to complement the official convex package.. Latest version: 0.1.104, last published: 6 days ago. Start using convex-helpers in your project by running npm i convex-helpers. There are 18 other projects in the npm registry using convex-helpers.
Oscar
OscarOP3mo ago
thank you!! !!!!!

Did you find this page helpful?