• steve_adams_86 5 hours ago

    I love Zod, but recently I've been converting to Effect's Data and Schema modules.

    Previously I liked a combination of Zod and ts-pattern to create safe, pattern matching-oriented logic around my data. I find Effect is designed far better for this, so far. I'm enjoying it a lot. The Schema module has a nice convention for expressing validators, and it's very composable and flexible: https://effect.website/docs/guides/schema/introduction

    There are also really nice aspects like the interoperability between Schema and Data, allowing you to safely parse data from outside your application boundary then perform safe operations like exhaustively matching on tagged types (essentially discriminated unions): https://effect.website/docs/other/data-types/data#is-and-mat...

    It feels extremely productive and intuitive once you get the hang of it. I didn't expect to like it so much.

    I think the real power here is that these modules also have full interop with the rest of Effect. Effects are like little lazy loaded logical bits that are all consistent in how they resolve, making it trivial to compose and execute logic. Data and Schema fit into the ecosystem perfectly, making it really easy to compose very resilient, scalable, reliable data pipelines for example. I'm a convert.

    Zod is awesome if you don't want to adopt Effect wholesale, though.

    • bjacobso 4 hours ago

      I've had a very similar experience, and have been slowly moving from zod and ts-rest to @effect/schema and @effect/platform/HttpApi as well as migration to Effect Match from ts-pattern. There is a learning curve but its a pretty incredible ecosystem once you are in it for a bit.

      I think the real turning point was typescript 5.5 (May 2024). The creator of typescript personally fixed a bug that unlocked a more natural generator syntax for Effect, which I think unlocks mainstream adoption potential.

      https://twitter.com/MichaelArnaldi/status/178506160889445172... https://github.com/microsoft/TypeScript/pull/58337

      • morbicer 4 hours ago

        I feel like Effect is today's Ramda. So cool but it's going to be regretted by you and people coming after you in few years. Me and my team reverted to more stupid code and we are happier.

        • steve_adams_86 3 hours ago

          I agree in some contexts. Kind of like Rust, I see a place for more durable code that's harder to reason about in some cases.

          I wouldn't use Effect for a lot of things. For some things, I'm very glad to have it. One thing Effect has going for it that Ramda didn't is that it's much less abstract and it's quite a bit more opinionated about some more complex concepts like error handling, concurrency, or scheduling.

          Kind of like state machines. You shouldn't use them for everything. For some things, it's a bad idea not to (in my opinion).

          Then of course subjectivity is a factor here. Some people will never like conventions like Effect, and that's fine too. Just write what feels right.

          • k__ 17 minutes ago

            Yes it's quite sad.

            I liked the idea of Ramda until I saw code bases that where using it for everything.

            I'm doing JS for over a decade now and I couldn't understand a thing.

            • bjacobso 4 hours ago

              that is certainly a possibility

            • dimal 2 hours ago

              How did you find learning Effect? The sales pitch sounds great, but when I went through the docs it seemed pretty confusing to me. I’m sure there are reasons for the everything but I couldn’t grok it. In particular, I’m thinking of the Express integration example.[0] I look at that and think, I need all that just to create a server and a route? What’s the benefit there? I’m hesitant to buy into the ecosystem after looking at that. I want to like it, though.

              [0] https://effect.website/docs/integrations/express

              • obeavs 16 minutes ago

                Hands down, the best (free, no email) resource to learn Effect is here https://www.typeonce.dev/course/effect-beginners-complete-ge..., as opposed to the docs. The link referenced gives a holistic view of how to incorporate it.

                • bjacobso an hour ago

                  I agree, some of there examples are a little overly complicated by their quest to be hyper composable. In fact they should probably remove that example. I am currently using it with Remix, and using their @effect/platform package to produce a simple web handler (request: Request) => Response (thank remix for heavily promoting the adoption of web standards).

                  I fully agree parts of the ecosystem are complex, and likely not fully ready for broad adoption. But I do think things will simplify with time, patterns will emerge, and it will be seen as react-for-the-backend, the de facto first choice. effect + schema + platform + cluster will be an extremely compelling stack.

                  • theschwa an hour ago

                    Yeah, looking at that example feels like jumping straight into the deep end of the pool. I think it helps going through a tutorial that breaks down the why of each piece. I really liked this tutorial on it: https://www.typeonce.dev/course/effect-beginners-complete-ge...

                    Some core things from Effect though that you can see in that Express example:

                    * Break things down into Services. Effect handles dependency injection, that's typed, for services so you can easily test them and have different versions running for testing, production, etc. * Fibers for threaded execution * Managing resources to make sure they're properly closed with scope

                    I think a lot of these things though often aren't truly appreciated until you've had something go wrong before or you've had to build a system to manage them yourself. *

                    • dimal 24 minutes ago

                      Yeah, this looks like the tutorial I needed. Thanks.

                  • steve_adams_86 3 hours ago

                    I agree about the turning point. Things have improved dramatically. And I know it probably doesn't feel the same for tons of people, but I love to see generators being used in every day code.

                    The learning curve just about turned me away from it at the start, but I'm glad I stuck with it.

                    I think learning Effect would actually teach a lot of people some very useful concepts and patterns for programming in general. It's very well thought out.

                  • Aeolun 11 minutes ago

                    I like the functionality, but the verbosity of the API makes me want to immediately ignore it. I feel like zod nailed the usability part.

                  • n00bskoolbus 34 minutes ago

                    Something cool that I can't remember if it was posted on HN at one point or I stumbled across when looking for alternatives to yup but this repo has been compiling a bunch of different benchmarks for runtime validation of ts validation libraries. Obviously to some degree the performance is arbitrary when you're reaching millions of operations per second but on the flipside their benchmarks are against rather data. Would be interested to see comparison of either more nested data or otherwise complex. Maybe something to look at in my spare time.

                    https://moltar.github.io/typescript-runtime-type-benchmarks/

                    • Cu3PO42 39 minutes ago

                      Zod has been a great boon to a project I've been working on. I get data from multiple sources where strong types cannot be generated and checking the schema of the response has caught a great number of errors early.

                      Another feature that I use intensively is transforming the response to parse JSON into more complex data types, e.g. dates but also project-specific types. In some situations, I also need to serialize these data types back into JSON. This is where Zod lacks most for my use-case. I cannot easily specify bidirectional transforms, instead I need to define two schemas (one for parsing, one for serializing) and only change the transforms. I have added type assertions that should catch any mistakes in this manual process, but it'd be great if I didn't have to keep these two schemas in sync.

                      Another comment mentioned @effect/schema [0], which apparently supports these encode/decode relationships. I'm excited to try it out.

                      [0] https://effect.website/docs/guides/schema/introduction

                      • threatofrain 6 hours ago

                        This is just a link to the front page of possibly the #1 most popular type validation library in the ecosystem? Anyways, ya'll might want to check out up-and-coming Valibot, which has a really nice pipe API.

                        https://valibot.dev

                        • k__ 8 minutes ago

                          I wrote my bachelor thesis with professor Kriha too.

                          Nice to see there is still coming awesome stuff from HdM in Stuttgart.

                          • rjknight 6 hours ago

                            Valibot is really nice, particularly for avoiding bundle size bloat. Because Zod uses a "fluent builder" API, all of Zod's functionality is implemented in classes with many methods. Importing something like `z.string` also imports validators to check if the string is a UUID, email address, has a minimum or maximum length, matches a regex, and so on - even if none of those validators are used. Valibot makes these independent functions that are composed using the "pipe" function, which means that only the functions which are actually used need to be included in your JavaScript bundle. Since most apps use only a small percentage of the available validators, the bundle size reduction can be quite significant relative to Zod.

                            • crooked-v 6 hours ago

                              Valibot also has much, much more efficient type inference, which sounds unimportant right up until you have 50 schemas referencing each other and all your Typescript stuff slows to a molasses crawl.

                              • zztop44 2 hours ago

                                Agreed. I recently moved a production app from Zod to Valibot for exactly this reason. I still slightly prefer Zod’s syntax but the performance issues were absolutely killing us.

                              • kaoD 6 hours ago

                                Does/will this correctly handle `| undefined` vs `?`, i.e. correct behavior under `exactOptionalPropertyTypes`?

                                Zod doesn't (yet[0]) and it's been a pain point for me.

                                [0] https://github.com/colinhacks/zod/issues/635

                                • x1000 6 hours ago

                                  I ran into exactly same pain point which was enough to nullify the benefits of using zod at all.

                                • Eric_WVGG 4 hours ago

                                  Is Valibot's error handling any good? Zod's is… like punishment for a crime I wasn't aware that I had committed.

                                  • Timon3 6 hours ago

                                    I recently stumbled onto this when looking for alternatives, and though it might sound a bit extreme: the style of documentation means I'll never consider it for any project. It's strange and honestly somehow unnerving to read documentation written from a first-person perspective. Is there some good reason for this that I'm missing? Or am I just crazy and this isn't an issue for anyone else?

                                    • Bjartr 6 hours ago

                                      I only see second-person "you" and not first-person "I" in the linked documentation. Am I missing what you intended to point out?

                                      In any case, this might actually be a good use for an LLM to post-process it into whatever style you want. I bet there's even a browser extension that could do it on-demand and in-place.

                                      • Timon3 5 hours ago

                                        Really? For example under "Main concepts" on the "Schemas" site[0], I see stuff like this:

                                        - I support the creation of schemas for any primitive data type.

                                        - Among complex values I support objects, records, arrays, tuples as well as various other classes.

                                        - For objects I provide various methods like pick, omit, partial and required.

                                        - Beyond primitive and complex values, I also provide schema functions for more special cases.

                                        Same for "Mental model", "Pipeline", "Parse data", "Infer types", "Methods" and "Issues" - I'll assume the other sections also follow this style. That's all not showing up for you?

                                        While the LLM suggestion is nice, it's not something I'm comfortable with unless hallucinations are incredibly rare. Why would I use a library whose documentation I have to pass through an unreliable preprocessor to follow a normal style?

                                        [0]: https://valibot.dev/guides/schemas/

                                        • prophesi 5 hours ago

                                          If they're part of Hacktoberfest, editing those pages to drop the first person perspective sounds like a pretty useful first contribution.

                                          • Timon3 4 hours ago

                                            It seems I'm not the first person to make this observation: https://github.com/fabian-hiller/valibot/issues/687

                                            I honestly don't want my validation library to "tell a story" at the expense of documentation clarity. It's absolutely fine that this project uses it, I don't want to impose my view on them - I guess it's just not the validation library for me.

                                      • skybrian 3 hours ago

                                        It's a little too cute, but I don't see it as a deciding factor on which library to use.

                                        I think a more important issue is that Valibot hasn't reached 1.0 yet. But it looks like it's very close.

                                        • kaoD 5 hours ago

                                          > Or am I just crazy and this isn't an issue for anyone else?

                                          Not an issue for me, to be honest. Why does it bother you at all?

                                          • Timon3 4 hours ago

                                            I'm not exactly sure myself, but every time I open one of the pages, I mentally stumble over the formulations. I think there are two components:

                                            1. The biggest part is that I've simply never seen documentation written in this style, any mentions of "I" or "we" are usually explaining the choices made by the author(s). When skimming documentation I pay more attention to those parts. Here those parts don't have a comparable meaning.

                                            2. The smaller part is that the writing style reminds me of the way brands use mascots with first-person writing to advertise to children. There's not really any other association I have with this way of writing, and it makes me feel like the author either isn't taking the project seriously, or me.

                                            I'm not trying to argue that the documentation should be understood this way, or that it should be changed - but I've stumbled over this multiple times, and can't imagine that it's just me.

                                        • mightyham 5 hours ago

                                          I'm currently using valibot and the author's associated modular form library in a production app and can vouch that it's been very pleasant to work with.

                                          • hyperbrainer 3 hours ago

                                            Maybe OP is one of the lucky 10,000. https://xkcd.com/1053/

                                            • sergiotapia 6 hours ago

                                              A whole lot of yapping and ZERO code on the homepage. Authors should remove 90% of the stuff on that landing page, jesus!

                                              also since zod is the de facto validation lib, might be worth a specific page talking about why this vs zod. even their migration from zod page looks nearly identical between the two packages.

                                              • petesergeant 6 hours ago

                                                On the front page there is a prominent section addressing the differences from Zod, which appear to be “much better performance”

                                            • dhruvrajvanshi 5 hours ago

                                              I wonder about a Typescript with alternate design decisions. The type system is cool and you can do a lot of compile time metaprogramming. However, when there's a type error in computed types, it's a nightmare to visually parse

                                                type { foo: ... , bar: ..., ... } can't be assigned to type { foo: ..., bar: ... }. type { foo: ... bar: ..., ... } is missing the following properties from { foo: ..., bar: ..., ... }
                                              
                                              Apart from repeating roughly the same type 4 times (which is a UX issue that's fixable), debugging computed types requires having a typescript interpreter in your head.

                                              I wonder if we had nominal runtime checked types, it could work better than the current design in terms of DX. Basically, the : Type would always be a runtime checked assertion. Zod certainly fills that gap, but it would be nicer to have it baked in.

                                              The type system would not be as powerful, but when I'm writing Kotlin, I really don't miss the advanced features of Typescript at all. I just define a data class structure and add @Serializable to generate conversions from/to JSON.

                                              • wrs 5 hours ago

                                                TypeScript has a crazy powerful type system because it has to be able to describe any crazy behavior that was implemented in JavaScript. I mean, just take a look at @types/express-serve-static-core [0] or @types/lodash [1] to see the lengths TS will let you go.

                                                If you write in TS to start with, you can use a more sane subset.

                                                [0] https://github.com/DefinitelyTyped/DefinitelyTyped/blob/mast...

                                                [1] https://github.com/DefinitelyTyped/DefinitelyTyped/blob/mast...

                                                • dhruvrajvanshi 4 hours ago

                                                  Right. I'm aware. My point was that even though the type system is powerful, somehow, I'm able to represent everything I need to in Kotlin's type system just fine and it feels a lot more type safe because it will throw a type error at runtime in the right place if I do a bad cast.

                                                  Typescript `as Foo` will not do anything at runtime, and it will just keep on going, then throw a type error somewhere else later (possibly across an async boundary).

                                                  You can, in theory use very strong lint rules (disallow `as` operator in favour of Zod, disallow postfix ! operator), but no actual codebase that I've worked on has these checks. Even the ones with the strictest checks enabled have gaps.

                                                  Not to mention, there's intentional unsoundness in the type system, so even if you wanted, you couldn't really create a save subset of TS.

                                                  Then there's the issue of reading the library types of some generic heavy code. When I "go to definition" in my fastify codebase, I see stuff like this

                                                    RouteHandlerMethod<RawServer, RawRequest, RawReply, RouteGeneric, ContextConfig, SchemaCompiler, TypeProvider, Logger>
                                                  
                                                  Which expands to this

                                                    export type RouteHandlerMethod<
                                                    RawServer extends RawServerBase = RawServerDefault,
                                                    RawRequest extends RawRequestDefaultExpression<RawServer> = RawRequestDefaultExpression<RawServer>,
                                                    RawReply extends RawReplyDefaultExpression<RawServer> = RawReplyDefaultExpression<RawServer>,
                                                    RouteGeneric extends RouteGenericInterface = RouteGenericInterface,
                                                    ContextConfig = ContextConfigDefault,
                                                    SchemaCompiler extends FastifySchema = FastifySchema,
                                                    TypeProvider extends FastifyTypeProvider = FastifyTypeProviderDefault,
                                                    Logger extends FastifyBaseLogger = FastifyBaseLogger
                                                  > = ( this: FastifyInstance<RawServer, RawRequest, RawReply, Logger, TypeProvider>, request: FastifyRequest<RouteGeneric, RawServer, RawRequest, SchemaCompiler, TypeProvider, ContextConfig, Logger>, reply: FastifyReply<RouteGeneric, RawServer, RawRequest, RawReply, ContextConfig, SchemaCompiler, TypeProvider> // This return type used to be a generic type argument. Due to TypeScript's inference of return types, this rendered returns unchecked. ) => ResolveFastifyReplyReturnType<TypeProvider, SchemaCompiler, RouteGeneric>

                                                  Other languages somehow don't need types this complicated and they're still safer at runtime :shrug:

                                                  • rimunroe 3 hours ago

                                                    > You can, in theory use very strong lint rules (disallow `as` operator in favour of Zod, disallow postfix ! operator), but no actual codebase that I've worked on has these checks. Even the ones with the strictest checks enabled have gaps.

                                                    That's surprising. I've worked on a few codebases with reasonably mature TS usage and they've all disallowed as/!/any without an explicit comment to disable the rule and explain why the use is required there.

                                                    • wrs an hour ago

                                                      It's apples and oranges. The type system in Kotlin is integrated into the language. TypeScript is a preprocessor for JavaScript that isn't allowed to change the JavaScript language, or have any runtime.

                                                      The "as Foo" construct is for you to tell TS that you know better than it, or that you deliberately want to bypass the type system. You can have a runtime check, but you have to write the code yourself (a type predicate), because TS doesn't write or change any JavaScript*, it just type-checks it.

                                                      I've certainly worked in new codebases where a relatively simple subset of TS types were used. Even then there were a few places the crazy type system was helpful to have. For example, we enforced that the names of the properties in the global configuration object weren't allowed to have consecutive uppercase letters!

                                                      (* with minor exceptions like transpiling for new JS features)

                                                  • mhh__ an hour ago

                                                    Can you do any compile time metaprogramming in typescript?

                                                    • rlp 5 hours ago

                                                      This is my exact experience. TypeScript seemed to hit a complexity sweet spot about 5 years ago, then they just kept adding more obscure stuff to the type system. I find that understanding TypeScript compiler errors can be almost as difficult as understanding C++ template errors at times.

                                                      • phplovesong 5 hours ago

                                                        This. Haxe is a more sane TS alternative in 2024.

                                                        • jadbox an hour ago

                                                          It's Haxe still been actively developed? I loved it back in the day. The blog hasn't had an update in years.

                                                      • spencerchubb 5 hours ago

                                                        Couldn't this be improved by showing a diff between the mismatched types?

                                                        • dhruvrajvanshi 4 hours ago

                                                          Yes, I did mention that the UX of the type errors could be improved and probably should, but once you start getting into conditional types, and nested types (which may not be fully expanded when you see the error), it gets hairy.

                                                      • timpetri 6 hours ago

                                                        Looking around on Twitter and repos in the OSS community, it appears that Zod is now almost always favored over yup, despite an almost identical API. Curious to hear what people think if they've worked with both. We went with Yup early on at my company, and now that's what we use for consistency in our codebase. I haven't personally found it to be lacking, but some of the logic around nulls and undefined always lead me back to the docs.

                                                        • roessland 5 hours ago

                                                          My company used Yup initially but we moved to Zod to be able to infer types from schemas. For example, API response payloads are Zod schemas. OpenAPI components are also generated from Zod schemas.

                                                          There are some performance issues, and WebStorm is struggling, which forced me over to VS Code.

                                                          But overall pretty happy.

                                                          • kabes 5 hours ago

                                                            But Yup also allows to infer types from schemas...

                                                        • agluszak 2 hours ago

                                                          Could someone explain to me what problem exactly Zod solves?

                                                          Why do you need to do `type User = z.infer<typeof User>;` instead of declaring a class with typed fields and, idk, deriving a parser for it somehow? (like you would with Serde in Rust for example). I don't understand why Zod creates something which looks like an orthogonal type hierarchy.

                                                          For context: I come from the backend land, I enjoy strong, static typing, but I have very little experience with JS/TS and structural typing

                                                          • tubthumper8 an hour ago

                                                            > deriving a parser for it somehow

                                                            Serde in Rust does this with the Rust macro system, but TypeScript doesn't have a macro system. That's why people have to go the other way, the programmer defines the parser, then TypeScript can infer the type from the parser.

                                                            I have seen a library that invented their own macro system (a script that you configure to run before build, and it writes code into your node_modules directory), though I can't recall the name.

                                                            • arzig 2 hours ago

                                                              There’s no macro system in TS that could analyze the type to build the parser. So, you work the other way and build the parser and then produce the type from that.

                                                              • _heimdall 2 hours ago

                                                                Zod offers runtime type validation where typescript only does this at build time. You can also use it for data normalization, safely parsing date strings to Date objects for example.

                                                                • outlore 2 hours ago

                                                                  The “type User =“ statement creates a TypeScript type from the zod schema, which can be useful when passing that definition around to functions

                                                                  The schema object is useful for runtime validation, e.g. User.parse(). this is handy when validating payloads that come over the wire that might be untrusted. the output of the “parse()” function is an object of type User

                                                                  you can kind of think of it like marshaling Json into a struct in Go :)

                                                                  • xmonkee 2 hours ago

                                                                    The User object in your example is used to parse the data. Its the “somehow” part of your question. There is no way to go from a type to data in typescript (there is no runtime awareness of types whatsoever) so zod solves this by you writing the zod object and then deriving the type from it. Basically you only have to weite one thing to get the parser and the type.

                                                                    • cheriot 2 hours ago

                                                                      I used it to validate data from config files matched the schema. I imagine it could be useful for other sources of suppose-to-be-structured data like an http body.

                                                                    • Stoids 5 hours ago

                                                                      The fragmentation around runtime validation libraries is pretty crazy. The fact that half these comments mention some alternative library that mimics almost the exact API of Zod illustrates that.

                                                                      It is filling a necessary shortcoming in the gradual typing of TypeScript, and using validator schema types to power other APIs generic inference is powerful. I am optimistic about an obvious leader emerging, or at least a better story about swapping between them more easily, but a bit annoying when trying to pick one to settle on for work that I have confidence in. That being said, Zod seems like the community favorite at the moment.

                                                                      • skybrian 2 hours ago

                                                                        Yes, it's annoying. I share your optimism. This is how the JavaScript (and now TypeScript) community figures things out.

                                                                        Note that TypeScript had competitors, too. It got better. Zod has an early lead and is good enough in a lot of ways, but I'm not sure it will be the one.

                                                                        Perhaps someday there will be a bun/deno-like platform with TypeScript++ that has validation merged in, but it's probably good that it's not standardized yet.

                                                                      • bjacobso 5 hours ago

                                                                        zod is great, but I have been moving to @effect/schema and think it deserves a mention here. @effect/schema is the evolution of io-ts, which originally inspired zod.

                                                                        It supports decoding as well as encoding, and fits natively into the rest of the effect ecosystem.

                                                                        https://effect.website/docs/guides/schema/introduction

                                                                        It does come with the cost of importing effect, so might not be the best in certain scenarios. However, there are smaller options than zod if that is a concern.

                                                                        • obeavs 4 hours ago

                                                                          Yep. Effect is so cool. The ability encode AND decode is tomorrow's standard.

                                                                          With all the work they're doing on durable workflows, hard to imagine that 2025 is anyone else's year.

                                                                        • vorticalbox 6 hours ago

                                                                          At work I have used zod, myzod, joi though I have settled on class-validator as it ties in with nestjs really well.

                                                                          • leontrolski 5 hours ago

                                                                            For those of you from a Python background - this is basically "Pydantic for Typescript". See also trpc - cross client/server typing using zod under the hood - https://trpc.io/

                                                                            • BenoitP 4 hours ago

                                                                              And thus custom validation goes to json, completing a what is old is new again cycle. After XML/XSD, after CORBA.

                                                                              • dgellow 5 hours ago

                                                                                Zod is fantastic, we use it pretty extensively at Stainless. Definitely one of my favorite JS library. Not calling it a parser combinator was a really good marketing move

                                                                                • molszanski 5 hours ago

                                                                                  I very much enjoy more an alternative. Sadly much less hyped https://arktype.io/

                                                                                  • threatofrain 5 hours ago

                                                                                    What do you like most about arktype?

                                                                                  • psadri 6 hours ago

                                                                                    One thing to note about zod - it clones objects as it validates (parses) them. Eg z.array(z.object()) with an array of 10k objects will result in 10k cloned objects → slow.

                                                                                  • diggan 6 hours ago

                                                                                    As someone who never jumped onto the TypeScript hype-wagon, what is this for? Is this something like clojure.spec by for TypeScript so you can do runtime validation of data instead of compile-time validation?

                                                                                    Basically joi (https://joi.dev/api/?v=17.13.3) but different in some way?

                                                                                    • _fat_santa 6 hours ago

                                                                                      I think the killer feature of Zod is type inference. Not sure if Joi has support for it yet but you can take a zod schema and wrap it in `z.infer` to get the typescript type.

                                                                                      Personally I use zod in my API for body validations, it's super nice to write the schema then just use `type Body = z.infer(schema)` to get the TS type to use inside the code.

                                                                                      • threatofrain 5 hours ago

                                                                                        That's table stakes for this niche.

                                                                                      • newaccountman2 6 hours ago

                                                                                        > Is this something like clojure.spec by for TypeScript so you can do runtime validation of data instead of compile-time

                                                                                        not really "instead", more like "in addition to". Even if your code compiles, if you are receiving data, e.g., via API, then you need to check that it actually conforms to the type/schema you expect. What is run is JS, so it, sadly, won't just crash/error if an object that is supposed to be of `type Cat = {name: string, ownerId: number}` lacks an `ownerId` at runtime.

                                                                                        Have you used Pydantic in Python? It's like that, but feels worse, IMO lol. I say this because Pydantic fits into writing Python code much more naturally than writing Zod stuff fits into writing TypeScript, IMO.

                                                                                        • naberhausj 6 hours ago

                                                                                          I've not used either, but it appears to be similar to JOI, yes.

                                                                                          The main distinction is that ZOD allows you to extract a TypeScript type from your schema. This means you get both compile-time and run-time type checking.

                                                                                          • VoidWhisperer 6 hours ago

                                                                                            Correct on the part of it being a runtime validation of data library (I can't as easily speak to whether or not it is similar to joi, never used it)

                                                                                            • valbaca 6 hours ago

                                                                                              yep.

                                                                                              Typescript is build-time validation, but in the end TS is "just JS"

                                                                                              Zod provides runtime validation (and also works well with TS)

                                                                                              • molszanski 5 hours ago

                                                                                                Deepkit.io has cool validations in runtime based on TS, but it is whole another level.

                                                                                            • aleksiy123 5 hours ago

                                                                                              Does anyone have a nice combination of tooling for typed handlers + client generation.

                                                                                              Thinking maybe Zod + Zod open API.

                                                                                              Really looking to replicate similar spec first workflow similar to protobuf services.

                                                                                              https://typespec.io/ also looks promising but seems early.

                                                                                              • mnahkies 5 hours ago

                                                                                                My tool https://openapi-code-generator.nahkies.co.nz/overview/about generates typed handlers based around koa (routing, req/res validation using zod) from openapi 3, as well as typed clients with optional zod validation using fetch/axios.

                                                                                                It also supports typespec using their transpilation to openapi 3 tooling

                                                                                                • bjacobso 5 hours ago

                                                                                                  I think you are looking for https://ts-rest.com/

                                                                                                  • kaoD 5 hours ago

                                                                                                    Nice. I'm looking to migrate away from a legacy custom framework over Express and this could help.

                                                                                                    If someone has tried both, can anyone share how it compares with tRPC[0]?

                                                                                                    [0] https://trpc.io/

                                                                                                    • bjacobso 5 hours ago

                                                                                                      From my understanding trpc is very similar, however, the rpc mechanism is not a standard. ts-rest produces openapi schemas and speaks REST over http, as well as a typed client.

                                                                                                      That being said, I am actually slowly migrating off ts-rest and adopting @effect/schema and @effect/platform/HttpApi, I foresee this being the direction the typescript ecosystem heads in over the next few years. However, the APIs are not stable yet and it has a bit of a learning curve, so would not adopt lightly

                                                                                                      • AWebOfBrown 2 hours ago

                                                                                                        I really wanted to adopt tRPC but the deal breaker was it being opinionated on status codes without allowing configurability. Because I needed to meet an existing API spec, that meant ts-rest was a better option. I think there's an aditional option with a native spec generator in frameworks like Hono, and maybe Elysia.

                                                                                                  • brap 5 hours ago

                                                                                                    I always found it pretty awkward that you even need libraries like this. A limitation of TS I suppose.

                                                                                                    • root_axis 5 hours ago

                                                                                                      I prefer typebox because it uses JSON schema. As far I'm aware it's otherwise on par with Zod, but I might be unaware of some capabilities of Zod that typebox lacks.

                                                                                                      • bearjaws 5 hours ago

                                                                                                        One of the brilliant decisions of the AI SDK from Vercel was to use Zod.

                                                                                                        It makes tool calling and chaining very robust, despite how finicky LLMs can be.