Gorka Cesium
Gorka Cesium3y ago

Schema / Types things

I would like to know which would be the ideal pattern to type a schema in convex so it plays well with a typed language like TS or Rescript. My original idea would be to write the schema, for example:
type Customer = {
name: string,
email: string
}
type Customer = {
name: string,
email: string
}
But then I have two queries in the app that fetch different parts of the customer.
query getCustomers : array<Customer({ name, email })>

query getCustomerEmail : Customer({ email })
query getCustomers : array<Customer({ name, email })>

query getCustomerEmail : Customer({ email })
In this case would I need to create an additional type for the response getCustomerEmail?
10 Replies
jamwt
jamwt3y ago
@alexcole @ballingt are the experts on Convex schemas + types
ballingt
ballingt3y ago
@Gorka Cesium to back up a bit, Convex looks for a schema.ts file that uses a lets you declare the types of the documents in your database, and then the types flow out from there. https://docs.convex.dev/using/schemas
Defining a Schema | Convex Developer Hub
End-to-end type safety requires typing your tables.
ballingt
ballingt3y ago
This is the really nicely supported flow, it would help to hear what you think of this flow as a jumping off point. Once you're using schema.ts file, the types of queries like getCustomers and getCustomerEmail will be inferred; you can even use these types in your codebase like ReturnType<typeof getCustomerEmail>.
Gorka Cesium
Gorka CesiumOP3y ago
sounds convenient. So in my case with Rescript I would have to build a util that generates the .d.ts to Rescript types so I can leverage automatic inference for TS it is taken care by npm convex dev if i understand correctly
ballingt
ballingt3y ago
Yes that sounds right, and how hard this is depends on some details of Rescript that I'm not familiar with. The "trick" we do with TypeScript is importing the types directly from the modules in the convex/ directory, so the codegen is very minimal.
Gorka Cesium
Gorka CesiumOP3y ago
I see, very cool That would save me from writing a lot of code
ballingt
ballingt3y ago
Are you hoping to write your Convex functions in JavaScript, but your frontend in Rescript? (someday you should be able to write your Convex functions in Rescript too! but right now the bundler is hardcoded in the CLI)
Gorka Cesium
Gorka CesiumOP3y ago
I think i would write as much as possible in Rescript since it transpiles to Js. Except a few functions where the type bindings get too tricky Would be great to have Rescript as a first class citizen in convex but I understand it might not be a priority due to the small user base How do you handle the case when you need to write a utility function that takes a param type Customer eg. validateCustomerEmail and you want to use it with the responses of getCustomerName and getCustomerEmail? I have used a data accesor similar to d3 utils so the type compiler doesn’t complain. I guess another way to make that param polyvariant but would be a lot of boilerplate
ballingt
ballingt3y ago
generally, you can't — the return type of getCustomerName and getCustomerEmail are different shapes. I need to learn more about Rescript's type system, but in many languages you could implement an interface that describes objects that have an email field, and pass that into validateCustomerEmail. In TypeScript, you don't need to write the interface except in the function signature.
function validateCustomerEmail(hasAnEmail: {email: string}): boolean { ... }
function validateCustomerEmail(hasAnEmail: {email: string}): boolean { ... }
Gorka Cesium
Gorka CesiumOP3y ago
Nice, maybe there’s something like that. Thanks I’ll look into it

Did you find this page helpful?