Live data from Hacker News

Zod 4

zod.dev

71–80 of 260 posts

Re: Zod 4

#71
post #5

Zod is a lot better than some of the alternative solutions I've seen. That said, the need for this sort of explicit validation always felt like a failure of where modern web development has taken us. It's so frustrating how full-stack development requires so many ways of describing the same shapes: JS input validation, Swagger for API definition, server-side input validation, ORM for schema conformance, and TypeScrip…

We use drizzle + Hono + client with zod. So the entire chain from ui to client to server to DB follow same validation and shape.

Re: Zod 4

#72

But how is the below possible - doesn't it need to include most of the TypeScript compiler? Does it compile the type definitions to some kind of validation structure (like how a compiled regex works) and then use just that? - Zero external dependencies - Works in Node.js and all modern browsers - Tiny: 2kb core bundle (gzipped)

The TypeScript compiler is only needed during development, the compiled JavaScript code contains no TypeScript-specific logic. Zod’s validation is entirely JavaScript-based, relying on simple checks (e.g., typeof, regexes, comparisons).

Also, the 2kb bundle just for the zod/v4-mini package, the full zod/v4 package is quite large.

Re: Zod 4

#74
post #59

Earlier quoted context omitted.

I think you would use discrimated unions. const MyResult = z.discriminatedUnion("status", [ z.object({ status: z.literal("success"), data: z.string() }), z.object({ status: z.literal("failed"), error: z.string() }), ]); You can define passthrough behavior if there are a bunch of special attributes for a moderator but you don't want to list/check them all. With different methods that have different schema- If they sha…

Hmm, this is pretty interesting, but I still have issues. While Zod seems to be able to transform my server-returned object into a discriminated union, it doesn't seem to be able to tell which of the unions it is. For instance, say that api/user/mod-panel (e.g.) returns only moderator user objects. My API endpoint already knows that it will have moderator-related fields, but Zod forgets that when I parse it.

I am not totally sure what your API's look like but if you know the API only has a certain type (or subset of types), you would only validate that type on the method. Don't use a single union for everything.

Here is some pseudocode.

Person = { name: string, height: number }

Animal = {name: string, capability: string}

A = { post: object, methodType: string, person: Person }

ModeratorA = { post: object, moderatorField1: string, moderatorField2: string, person: Person }

UnionA = A && ModeratorA (There's probably a better way of defining A and ModeratorA to share the shared fields)

B = { post: object, animal: Animal }

endpoint person parses UnionA

endpoint animal parses B

You don't put all of your types in one big Union.

Re: Zod 4

#75
post #45

Earlier quoted context omitted.

The problem with this is that your One True User shape tends to have a bunch of optional properties on it. e.g., in the user profile you fetch Post[], but in the user directory you don't, and so on with other joined properties. If every endpoint returns the One True User, then you end up needing to write conditional logic to guard against (say) `.posts` when you fetch users in the profile, even though you know that `…

In Typescript at least, if the discriminated union is set up correctly, you just need a single check of the type field. That lets TS narrow the type so it knows whether e.g. `.posts` is present or not.

I think I can do this, yes, but it becomes a very large amount of repetitive work.

Let's say I have api/profile (which has `.posts`) and api/user-directory (which does not). I define User as a discriminated union - one has type `user-with-posts` and one has type `user-no-posts`. OK, good so far. But now say I have a photo gallery, which returns photos on user. Now I have to add that into my discriminated union type, e.g. `user-with-posts-and-photos`, `user-with-posts-but-not-photos`, `user-with-no-posts-but-yes-photos`... and it gets worse if I also have another page with DMs...

Re: Zod 4

#76

Zod 4 looks good but even with their latest improvements, ArkType is still an order of magnitude faster. Sometimes for the sake of backward and syntax compatibility, it is difficult to make something much faster than a fully greenfield newer library. We recently did an analysis of all these types of tools for our project and decided to go with ArkType for partially this reason, the other was TypeScript ergonomics fel…

Interesting, that one didn't even appear in my research. I was specifically looking for typescript ergonomics too. Probably still not going to switch away from Zod, though.

Re: Zod 4

#77

But how is the below possible - doesn't it need to include most of the TypeScript compiler? Does it compile the type definitions to some kind of validation structure (like how a compiled regex works) and then use just that? - Zero external dependencies - Works in Node.js and all modern browsers - Tiny: 2kb core bundle (gzipped)

I think Zod uses JIT compilation via `new Function`, rather than including the entire TypeScript compiler. This method allows for concise validation logic, executing only what’s necessary at runtime.

Re: Zod 4

#78
post #59

Earlier quoted context omitted.

I think you would use discrimated unions. const MyResult = z.discriminatedUnion("status", [ z.object({ status: z.literal("success"), data: z.string() }), z.object({ status: z.literal("failed"), error: z.string() }), ]); You can define passthrough behavior if there are a bunch of special attributes for a moderator but you don't want to list/check them all. With different methods that have different schema- If they sha…

Hmm, this is pretty interesting, but I still have issues. While Zod seems to be able to transform my server-returned object into a discriminated union, it doesn't seem to be able to tell which of the unions it is. For instance, say that api/user/mod-panel (e.g.) returns only moderator user objects. My API endpoint already knows that it will have moderator-related fields, but Zod forgets that when I parse it.

You can use an ‘is’ method to pick out a type from union. Although, if union is discriminated, it’s discriminated with a ‘kind’ so you should be able to know which kind you received.

Re: Zod 4

#80
post #35

Congratulations to the Zod team on the new release. At the risk of sounding overtly negative, I can't help but shudder when I think about the number of breaking changes outlined in the migration guide. For projects that rely heavily on Zod, it feels like a daunting task ahead—one that will demand a lot of developer attention and time to navigate. Having maintained a few frontend projects that are 4-5 years old at wor…

I am 100% in agreement here. I operate a couple large Next.js apps and in the last year we've had to deal with Next.js 14 -> 15 which introduced a ton of breaking cache changes, Next.js pages -> app router, React 18 -> 19, Eslint 8 -> 9, and Tailwind 3 -> 4.

It's honestly been a nightmare, and I wish I had just built in Django instead. The Tailwind 3 -> 4 migration was probably among the most painful, which I was not expecting.

Post reply on HN