Live data from Hacker News

Designing the perfect TypeScript schema validation library

vriad.com

41–50 of 77 posts

Re: Designing the perfect TypeScript schema validation library

#41

This is great. I recently built a fairly large amount of functionality around io-ts, adding support for mixed required/optional fields, eliminating the need to deal with `Either` monads, and a whole lot of other stuff that's mostly just relevant to my company's usage. I think if this had been available at the time I was looking for an underlying library, it would have been a no brainer to choose this one. Worth notin…

FWIW, runtypes is now part of my standard utility kit (along with utility-types[0]) for every TypeScript project I start. I don't leave home without it, and (AFAIK) it checks off every box mentioned as a problem by the author of the article.

At my employer, I just whacked it straight into our new API codebase on day one and people took to it immediately. It's great, great stuff.

[0]: https://github.com/piotrwitek/utility-types

Re: Designing the perfect TypeScript schema validation library

#42
A while ago, I used this library called ts-interface-builder to generate runtime validation functions from TS types. It worked really well, I was able to use the types from my front-end without any modifications for back-end validation.

Also, used the inferred response types from endpoint functions and passed them back to the front-end to use with front-end fetch calls. This was probably the biggest improvement in terms of productivity and improving accuracy. Imagine every time you change an endpoint's response, any fetch calls that are impacted would just show errors at compile time/in your editor.

Re: Designing the perfect TypeScript schema validation library

#43
While I think this is pretty cool, given his use case (wanting to use a strongly typed client and server), I can't see why one wouldn't just use GraphQL with TypeScript on both the client and server. I've done this and I love it:

1. Define the GraphQL interface with GraphQL's typedef language. GraphQL then takes care of validating all the request and responses at runtime.

2. Use something like https://github.com/dotansimha/graphql-code-generator to generate all your TypeScript types from your GraphQL schema. Place these types on your resolvers and then you get compile-time type checking.

3. Since GraphQL actually exposes your schema as part of the endpoint, clients can use the same tool to keep their TypeScript types in sync, and get the same typing benefits when writing the client code.

Re: Designing the perfect TypeScript schema validation library

#45
post #33

I built something like this a few months ago but struggled to explain to almost everyone except die hard TypeScript fans what the big deal was. I explained it was all about the type inference from the schema so I could make guarantees across runtime boundaries. This is what I came up with, though this library looks like it may be more comprehensive than what I wrote. Struggled to come up with a good name to represent…

I guess it's something in the air! Given the popularity of the other libraries, it's surprising that there's isn't an optimal one.

And yeah, unless you've gone down the rabbit hole of type safety obsession, it's hard to understand the necessity of this. I like that you specifically call out REST API validation in your docs...the difficultly of type safe API implementation was what drove me to build zod.

I'm using Zod plus a hand-rolled codegen tool to implement an end-to-end type safe RPC API that validates all data at runtime AND generates a statically typed Typescript SDK for use on the client.

PS If people like the sound of that I might publish that too. Let me know if it sounds interesting.

Re: Designing the perfect TypeScript schema validation library

#47

Earlier quoted context omitted.

This looks interesting too, but the syntax fells really weird to me.

A goal was you can treat it Exactly like an "Interface". I agree it looks totally nonsensical but I think of it as a text replacement.

The assignment to class properties reminds me an awful lot of stuff I've seen in Python, particularly in Django/REST Framework.

But the class wrapping thing would just break my brain every time I tried to use it. Calling plain functions just feels a lot more natural to me.

Re: Designing the perfect TypeScript schema validation library

#48

I'd really like something like a compiler step/plugin to generate the validators from the declared typescript types.

You can generate JSON Schema from TS with this library: https://github.com/YousefED/typescript-json-schema It's certainly conceivable to build an equivalent for Zod but you'll eventually want to validate types that aren't expressible in TS (i.e. Integer).

This looks like it generates JSON Schema, but not runtime validators?

Re: Designing the perfect TypeScript schema validation library

#49

Earlier quoted context omitted.

Oh, I do want to add one bit of minor feedback for the author: one of the things I like about the io-ts interface is that fields/codecs are values unless they require a parameter (e.g. `t.string` vs `z.string()`). It's a little bit easier for me to read. It's also not clear to me at a glance whether calling `z.string()` is creating a new instance of something and whether that affects the behavior of a given schema.

I personally prefer to standardize everything as a function. It also leaves some breathing room in case I decide to include parameters as part of a future API augmentation.

I hope you'll give me the opportunity to try to convince you otherwise.

I understand the context of this is that io-ts puts an onerous emphasis on FP concepts and data structures. But FP principles, when applied in an effective and usable way, are quite good. The make it easier to reason about and maintain code.

One such principle is that a "function" with no parameters is a good sign that it will cause some kind of side effect. I sort of hinted at this when I questioned the design, when I said that it wasn't clear to me whether calling these functions was producing new instances and whether those new instances affect behavior.

I would also argue that leaving room to parameterize primitive types is leaving room to make a drastically more complicated API in the future. A `string` with "options" suddenly becomes its own sub-API.

While io-ts is more complicated, once learnt its API is more predictable. A `Type` is a value. An `interface` (or similar) type is a `Record`. Always. `Type`s can be augmented/composed/etc (and you may provide a function that accepts one or more `Type`s as parameters to accomplish that), but they always resolve to a value. The value can be reused without concern about side effects.

Re: Designing the perfect TypeScript schema validation library

#50

Something similar, but for flow and focused more on functional combinators https://github.com/appliedblockchain/assert-combinators

Is the repo private? I get a 404

Oh thank you, mistake, fixed.
Post reply on HN