holden
holden2y ago

Inferring full Typescript types from schema?

Hi friends! Trying out Convex for the first time (looks quite slick!), trying to migrate an existing NextJS app currently using vercel/postgres + Drizzle. Two questions so far: 1. It looks like there's no Date or timestamp data type? My current models have created/updated/viewed times. _creationTime is great, but if I wanted to add the others, should I use int/float myself? Is creationTime in UTC? 2. How can I infer the full TypeScript type of a schema object? E.g. if I do this, it's missing the _id/_creationTime system fields.
No description
7 Replies
ian
ian2y ago
1. Yes there isn't a built-in Date type. I'd recommend doing something like _creationTime does, which is milliseconds since epoch (UTC) 2. You have one quick way to get the type of a document, which is the Doc<'users'> type. If you want to make a validator that includes the _id and _creationTime, lmk. I made a little helper in the ai-town repo I can point to For dates, I find storing a utc string or timestamp, and a separate named timezone to be more reliable than translating between dates with and without timezones, or date strings that capture a UTC offset rather than the timezone name, since the offset changes throughout the year b/c of daylight savings, etc. ISO 8601 / RFC 3339 support string comparison and are more readable, so I prefer those over default Date formatting. (new Date()).toISOString() and new Date(isoString) make this easy
holden
holdenOP2y ago
Thanks! 1) Sounds good! Ok to use a v.number() for this, or should it be v.int64()? 2) Perfect, that's what I was looking for. I skimmed the Typescript docs earlier and didn't see anything, but now see the Doc type mentioned there. I also use enum types quite a big in zod/Drizzle. I don't see any native enum type in Convex. Should I just do this?
export const statusEnum = v.union(
v.literal("active"),
v.literal("archived"),
v.literal("deleted")
);
export const statusEnum = v.union(
v.literal("active"),
v.literal("archived"),
v.literal("deleted")
);
jamwt
jamwt2y ago
2. that's right. 1. as long as you don't mind having floats in your database (you don't need large integers, you won't be sharing these with other systems via streaming export anytime soon), I'd recommend you just use v.number(). we'll have betters support for JS numbers that are actually meant to be ints via some orm-like stuff in the near future but v.int64() will make your app have to deal with bigints all the time, which is a pain in the ass
holden
holdenOP2y ago
Got it, will stick with number, thanks!
holden
holdenOP2y ago
This is resolved, and works fine. But one minor nit is timestamps aren't rendered as dates in the dashboard (I guess _creationTime is special cased). Not a big deal, but maybe something that would help usability a bit.
No description
Indy
Indy2y ago
Yep thanks for the feedback!
ian
ian14mo ago
Times are now rendered as dates for other fields, and zod validators can be used for function argument validation, output validation, and (if you read the caveats in the article) schema definition: https://stack.convex.dev/typescript-zod-function-validation
Using Zod with TypeScript for Server-side Validation and End-to-End...
Use Zod with TypeScript for argument validation on your server functions allows you to both protect against invalid data, and define TypeScript types ...

Did you find this page helpful?