We’ve just released a new module in anvil-labs called zod
It’s very much inspired by the popular TypeScript equivalent zod.dev
It’s not tied to the UI so can be integrated with existing UI solutions
And since it’s not tied to the UI you can use the same validation on the server and client!
Other considerations
Since there’s no documentation yet the autocompletions should help somewhat
But for general questions on how to use it there’s always the anvil-labs discussion page
This is proof positive that a well-designed and -documented schema pays for itself in spades.
I can easily see a generalized schema definition document being distilled into schemas for REST, for Zod, for a user-interface builder, etc.
On skimming Zod’s documentation, it appears that Zod should be able to produce reusable parts of schemas. E.g.,
from anvil_labs import zod as z
human_age_years_t = z.integer().nonnegative().max(127)
joint_ages_t = z.object({
'primary': human_age_years_t,
'spouse': human_age_years_t,
})
Which would make sense. After all, if your app has dozens of “age” fields, why spell out the type every time, when, by giving it a name, you not only avoid duplication, but you actually document what the type is used for? What it means in the real world?
On the other hand, I’ve never seen any Zod examples like the above. Which suggests that you must spell it out every time.
Yes that will absolutely work. A schema is just a set of instructions for converting input to output.
Worth noting that the schema won’t mutate the data. i.e. When you give the object schema a dictionary to parse it will return a new dictionary (assuming the parse was successful).
I’m no expert on TypeScript, JavaScript, or Zod, so please bear with me. What’s the distinction between record, object, and mapping? I assume that each has a different set of use cases, else why offer more than one.
a dictionary, with specific keys and each key has a specific type.
We will likely change the name to z.typed_dict (Keeping z.object around for backwards compatibility)
z.record
This is like Python’s typing.Mapping a dictionary with a key type and value type. Think a dictionary used as a cache, where the keys are all integers, say, and the values are all the same type.
For example, to check inputs from an API. It’s impractical to check them manually, so it has to be done in code, to prevent the dreaded “garbage-in, garbage-out” syndrome.
Yes, we could all write our own sanity-check functions to do the same job. Zod, however, provides a cohesive framework, which helps simplify the code, make it more readable, and make it easier to combine validators to build bigger and better ones.
The scalability is especially important when, as in my case, I have data files with literally hundreds of distinct, highly-structured inputs…
What I especially like is that Zod follows solid design principles, which makes the whole thing much easier to think about – and to design for.
I like to use the “domain” concept from data design. A Domain is literally a mathematical set, a set of values. Since programs are mathematical procedures, in reasoning about program behavior, it helps to be able to pin down the Domain of each input. The more precisely we do that, the better we can reason.
Zod makes Domains real, in our programs. Real objects that we can name, query, reuse, build with, and make them do work for us.
Instead of the original Zod’s TypeScriptyness. Yes!
Took a few hours out to study JavaScript and TypeScript, and the TypeScript version now makes a lot more sense. Many Anvil users, of course, came to Anvil to get away from all of that!
A Pythonic version is absolutely the way to go here. I look forward to seeing how it adapts to Python. I’ll probably join the discussion. There’s a good, mathematically-solid foundation for this work, easy to reason about. Keeping that simplicity is, I hope, a design/implementation goal.