I have been using Zod validation library with typescript for a little while and been loving it.
This might be a very basic thing, but I am trying to figure out what would be best pattern to extend Zod Schema with class-like functionality.
For the sake of the example lets have a Vector3 schema like this:
const Vector3Schema = z.object({
x: z.number(),
y: z.number(),
z: z.number(),
})
type Vector3 = z.infer<typeof Vector3Schema>;
This is very nice to have type associated with the zod validation. No duplicate definitions, extremely clean. I like it.
The problem is how I should go on about extending Vector3 type with some class-like functionality.
Maybe this is my OOP background shining trough, but I would like to have some basic functionality associated with the type in a class-like manner, so it could be used like this:
let vec1 = Vector3Schema.parse({x:1, y: 2, z: 3});
let vec2 = Vector3Schema.parse({x:4, y: 5, z: 6});
let distance = vec1.distance(vec2);
vec1.normalize();
I could just create a separate class definition for Vector3 and use Zod only for validating the data passed to the constructor. But this will lead quickly to the same old problem: having to maintain class definition and validation logic separately.
So I guess the question is: is there a convenient way to parse Zod schema to a class instance? Or alternatively extend parsed type with additional functionality?
Or.. should I just let go of my grampa OOP ways and move forward with more functional style:
function normalize(v: Vector3) {...}
function distance(v1: Vector3, v2: Vector3) {...}
let vec1 = Vector3Schema.parse({x:1, y: 2, z: 3});
let vec2 = Vector3Schema.parse({x:4, y: 5, z: 6});
let distance = distance(vec1, vec2);
vec1 = normalize(vec1);
I would love to hear your ideas on this topic.