7 ms·
> Think about it. When you get JSON from an API, you don't just parse it as any and then write a bunch of if-statements. You use something like Zod to parse it
by jmull 1y ago
> Think about it. When you get JSON from an API, you don't just parse it as any and then write a bunch of if-statements. You use something like Zod to parse it directly into the shape you want. Invalid data? The parser rejects it. Done.
Isn’t writing code and using zod the same thing? The difference being who wrote the code.
Of course, you hope zod is robust, tested, supported, extensible, and has docs so you can understand how to express your domain in terms it can help you with. And you hope you don’t have to spend too much time migrating as zod’s api changes.
- akoboldfrying 1y agoYes, both are writing code. But nearly all the time, the constraints you want to express can be expressed with zod, and in that case using zod means you write less code, and the code you do write is more correct. > Of course, you hope zod is robust, tested, supported, extensible, and has docs so you can understand how to express your domain in terms it can help you with. And you hope you don’t have to spend too much time migrating as zod’s api changes. Yes, judgement is required to make depending on zod (or any library) worthwhile. This is not different in principle from trusting those same things hold for TypeScript, or Node, or V8, or the C++ compiler V8 was compiled with, or the x86_64 chip it's running on, or the laws of physics.
- jmull 1y agoSure... the laws of physics last broke backwards compatibility at the Big Bang, Zod last broke backwards compatibility a few months ago.
- bigstrat2003 1y agoYeah, the "parse, don't validate" advice seems vacuous to me because of this. Someone is doing that validation. I think the advice would perhaps be phrased better as "try to not reimplement popular libraries when you could just use them".
- remexre 1y agoThe difference between parse and validate is function parse(x: Foo): Bar { ... } const y = parse(x); and function validate(x: Foo): void { ... } validate(x); const y = x as Bar; Zod has a parser API, not a validator API.
- dwattttt 1y agoSibling says this with code, but to distil the advice: reflect the result of your validation in the type system. Then instead of validating a loose type & still using the loose type, you're parsing it from a loose type into a strict type. The key point is you never need to look at a loose type and think "I don't need to check this is valid, because it was checked before"; the type system tracks that for you.
- 8n4vidtmkvmk 1y agoEveryone seems hung up on the type system, but I think the validity of the data is the important part. I'd still want to convert strings to ints, trim whitespace, drop extraneous props and all of that jazz even if I was using plain JS without types. I still wouldn't need to check the inputs again because I know it's already been processed, even if the type system can't help me.
- dwattttt 1y agoThe type isn't just there to make it easy to understand when you do it, it's for you a year later when you need to make a change further inside a codebase, far from where it's validated. Or for someone else who's never even seen the validation section of code. I'm hung up on the type system because it's a great way to convey the validity of the data; it follows the data around as it flows through your program. I don't (yet) Typescript, but jsdoc and linting give me enough type checking for my needs.
- k3vinw 1y agojsdoc types are better than nothing. You could switch to using Typescript today and it will understand them.
- MrJohz 1y agoI think the key part, although the author doesn't quite make it explicit, is that (a) the parsing happens all up front, rather than weaving validation and logic together, and (b) the parsing creates a new structure that encodes the invariants of the application, so that the rest of the application no longer needs to check anything. Whether you do that with Zod or manually or whatever isn't important, the important thing is having a preprocessing step that transforms the data and doesn't just validate it.
- makeitdouble 1y agoThe base assumption is parsing upfront cost less than validating along. I thinks it's a common case, but not common enough to apply it as a generic principle. For instance if validating parameter values requires multiple trips to a DB or other external system, weaving the calls in the logic can spare duplicating these round trips. Light "surface" validation can still be applied, but that's not what we're talking about here I think.
- MrJohz 1y agoIt's not about costing less, it's about program structure. The goal should be to move from interface type (in this case a series of strings passed on the command line) to internal domain type (where we can use rich data types and enforce invariants like "if server, then all server properties are specified") as quickly as possible. That way, more of the application can be written to use those rich data types, avoiding errors or unnecessary defensive programming. Even better, that conversion from interface type to internal type should ideally happen at one explicit point in the program - a function call which rejects all invalid inputs and returns a type that enforces the invariants we're interested in. That way, we gave a clean boundary point between the outside world and the inside one. This isn't a performance issue at all, it's closer to the "imperative shell, functional core" ideas about structuring your application and data.
- lmm 1y ago> if validating parameter values requires multiple trips to a DB or other external system, weaving the calls in the logic can spare duplicating these round trips Sure, but probably at the cost of leaving everything in a horribly inconsistent state when you error out partway through. Which is almost always not worth it.
- deleted 1y ago[deleted]