RJ
RJ3y ago

Recursive + `any` schema types

Related questions: - Is there any way to define a recursive SchemaType? - Is there any way to describe an untyped field in a [typed] schema? Consider:
export default defineSchema({
myTable: defineTable({
typedThing: s.array(s.string()),
untypedThing: s.any(),
})
})
export default defineSchema({
myTable: defineTable({
typedThing: s.array(s.string()),
untypedThing: s.any(),
})
})
10 Replies
alexcole
alexcole3y ago
More good questions! Yeah, there is no way to do a recursive schema fields, but you can use the workaround from https://discord.com/channels/1019350475847499849/1037457654664134808/1037468984154525847 to create other recursive types. Similarly, you can simulate an any with something like:
const schemaAny: SchemaType<any, string> = new SchemaType();
const schemaAny: SchemaType<any, string> = new SchemaType();
Same warning as with JSON that this might break in future versions of Convex. Also be aware that this allows you to attempt to serialize types that Convex doesn't support (ex new Date(), undefined).
RJ
RJOP3y ago
Interesting, good to know! I guess what I'd really want then is an "any valid SchemaType construction" SchemaType
alexcole
alexcole3y ago
Yeah, for sure. I think this is somewhat tricky/inconvenient to do in TypeScript. We could build an s.any that is a union of every type, but then you'd have to explicitly check the type of it before using the value. For example you couldn't pass it to a function that expects a string until you check that it's a string. But yeah I think having some type of any construct would be nice so you can bail out of using a schema for part of your data model.
RJ
RJOP3y ago
It would be useful particularly on the sending side—so that I can send a value to a Convex endpoint and know that it won't fail to persist. In other words, it would be nice to know if my value of type T extends AnyConvexType. On the receiving side I am probably shunting it off to some library or something which takes any or unknown, or am doing some runtime validation with something like io-ts or zod, which I think would not be a problem as well A user could always cast it as any themselves also, but maybe better to leave that to them if they want to in particular places?
alexcole
alexcole3y ago
Got it. Makes sense for your use case.!This is also kinda hard to do in TypeScript because TypeScript always allows objects to have extra properties and those could contain types that Convex doesn't support. But I think talking about this I'm also excited about having an s.any() that just bails out of using a schema for that part. I suspect that would make schemas easier to adopt.
RJ
RJOP3y ago
Ah yes you’re right, good point! Reflecting on it more though, I think my example T extends AnyConvexType was just bad/misleading—I don’t think a user (or I, at least) would interact with AnyConvexType like that. I think that I would have something of MyType and would try to pass it as an argument to db.insert. In that case, I think TypeScript would just do it’s classic structural type comparison thing and all would work as hoped?
RJ
RJOP3y ago
If not, there are also utility types like https://github.com/sindresorhus/type-fest/blob/main/source/jsonify.d.ts that might help?
GitHub
type-fest/jsonify.d.ts at main · sindresorhus/type-fest
A collection of essential TypeScript types. Contribute to sindresorhus/type-fest development by creating an account on GitHub.
RJ
RJOP3y ago
I’m not exactly sure though Anyways yeah, some form of “type hole” in a schema definition seems like it could be nice, however that’s effected!
ian
ian3y ago
Following up here, we now have s.any() to replace schemaAny
ian
ian3y ago
We also now have { strict: false } as a parameter to defineSchema if you want a partially defined table, or to not have to specify all your tables. I also just wrote a blog post on using zod with Convex: https://stack.convex.dev/wrappers-as-middleware-zod-validation
Zod Validation: Wrappers as “Middleware”
Function validation is important for a production app because you can’t always control which clients are talking to your server. See how to use zod to...

Did you find this page helpful?