I'm trying to achieve schema versioning / schema evolution / schema migration using zod. I guess zod isn't meant to be used this way, however I got a simple working prototype and wanted to get an opinion if this approach works, scales or if I should drop it and try to use different zod APIs or a completely different library. I would like to stick with zod though as its works quite nice and we already use it for our schema validations.
Basically, what I try to achieve is having different versions of a schema, which would be able to map all versions to the "latest" type - allowing me to modify types and schemas over time and still be able to parse "old" objects from a previous version of the schema.
For example, imagine a User type with only one string property id. Objects of type User are written to some persistence layer. Over time, Users are extended by another string property name. Again after some time, the name field is renamed to userName. There are possibly three different versions of type User in the persistence layer and I am not able to do database migrations. So we end up with these versions:
So my idea was to use a combination of .transform(), .or() and .pipe() to basically create "schema migrations", which would be able to lift v1 to v2, v2 to v3, and so on. In the end, I came up with the following solution:
One can already see, that this approach might be prone to errors and mistakes, createSchema is not really typesafe, especially regarding the evolutions array and also the order is really important.
I'm trying to achieve schema versioning / schema evolution / schema migration using zod. I guess zod isn't meant to be used this way, however I got a simple working prototype and wanted to get an opinion if this approach works, scales or if I should drop it and try to use different zod APIs or a completely different library. I would like to stick with zod though as its works quite nice and we already use it for our schema validations.
Basically, what I try to achieve is having different versions of a schema, which would be able to map all versions to the "latest" type - allowing me to modify types and schemas over time and still be able to parse "old" objects from a previous version of the schema.
For example, imagine a User type with only one string property
id
. Objects of type User are written to some persistence layer. Over time, Users are extended by another string propertyname
. Again after some time, thename
field is renamed touserName
. There are possibly three different versions of type User in the persistence layer and I am not able to do database migrations. So we end up with these versions:v1: { id: string } v2: { id: string, name: string } v3 (latest): { id: string, userName: string }
In my application, I only want to deal with latest User type
Parsing objects conforming the "latest" schema obviously works, but will break for older objects
So my idea was to use a combination of
.transform()
,.or()
and.pipe()
to basically create "schema migrations", which would be able to lift v1 to v2, v2 to v3, and so on. In the end, I came up with the following solution:Concrete solution for the different versions of User:
One can already see, that this approach might be prone to errors and mistakes,
createSchema
is not really typesafe, especially regarding theevolutions
array and also the order is really important.Is there a better approach using zod?