What does HackerNews think of io-ts?

Runtime type system for IO decoding/encoding

Language: TypeScript

#1 in PHP
#1 in TypeScript
#3 in TypeScript
You can use io-ts [0] to define your types, and it'll generate functions to typecheck for you. Syntactically it's a bit gnarly and the documentation isn't great; a first-party solution would definitely be nicer. But it works, and it's amazing that it works.

[0] https://github.com/gcanti/io-ts

That's nowhere near "falling apart". That's just the simple fact there's no silver bullet.

Someone arguing a little defensive programming is equivalently strong to a type system is clearly unaware just how much work a good type system does for you. I of course agree with you: when you're fetching data that you don't know the type of, recklessly casting it to some type is going to cause issues. This is true in every language that has ever existed. It's also why tools like IO-TS[0] exist, and of course you can enforce this with JSON Schema techniques or custom validators or a million other options.

Edit: in case the ultimate point of this comment is not clear, by using a type system and some type validator on your fetches, you are able to reduce the need for defensive programming exclusively to your fetch points. Clearly, defensive programming at the fetch points was already needed, so this is why I do not agree with the claim TypeScript's value add disappears from remote fetches.

[0]: https://github.com/gcanti/io-ts

Use io-ts: https://github.com/gcanti/io-ts

You define a decoder schema, and then the resulting TS type gets automatically derived for you. You can then run data through the decoder, it will err if there's a mismatch, or return a value of the inferred type otherwise.

Sure, if you're validating some data there're loads of better ways to do it than a bunch of conditionals. I was purely commenting on the switch(true) pattern vs some "if"s.

That approach looks nice though. On that subject, JS has some nice libraries including io-ts[1] which has a functional approach using Eithers to encapsulate errors/success.

[1]: https://github.com/gcanti/io-ts

Doing runtime-typechecks really is a blessing, and it would be great if typescript would provide this as a language-feature. There are two more libraries I know which are great for that:

* Zod: https://github.com/colinhacks/zod * io-ts: https://github.com/gcanti/io-ts (for the more functional-programming-oriented)

Type guard in the example should use runtime type checkers or codec like io-ts (https://github.com/gcanti/io-ts), otherwise it will just become a type-assertion with partial correctness.

With codec, one can make sure that the type is correct and defining type and type-guard becomes a one-time task.

Also, for using type guards to validate incoming data, check out https://github.com/pelotom/runtypes.

Or if brave enough to dive into the deep end of FP, io-ts is nice. https://github.com/gcanti/io-ts

I think the idea is that you validate the data once, on an API level. You don't need to validate the same data again after the initial inspection.

In our team we use io-ts to validate all of our endpoints, but simple type guards could achieve the same goal.

https://github.com/gcanti/io-ts

None are ready for the public yet, but all in the hopper or under serious consideration:

- Personal site/blog with a bunch of algorithmically generated art and other fun stuff, built on Node/Preact but progressively enhanced/almost completely JS-free at runtime. Motivation for the build approach is that I’m on the low/no client JS static site bandwagon but I quite like the DX of JSX components and CSS-in-JS.

- I’m using a few excellent existing tools[1][2] for said site which unfortunately aren’t designed to work well together, so I have a variety of wrapper tooling that makes them live peacefully together. I’m also developing a bunch of other build-stage tools for my use cases. I plan to open source (or hopefully contribute back) all of that as soon as I’m satisfied with their quality.

- A set libraries for building declarative, type safe, automatically validated/documented service API boundaries (HTTP/REST to start, but I also plan to support other transport protocols) — think io-ts[3] type interfaces but you get swagger docs for free in a transport-agnostic interface. I’ve built this kind of thing before, it was wildly successful in real world use, but it’s proprietary to a previous employer and I’m starting over with all the stuff I learned in hindsight.

- A “nag me” app that’s basically “reading list” plus “reminders” with minimal config, eg “nag me soon” or “nag me after a while”. My personal use case is I frequently screenshot/text myself/etc stuff I want to look at later (usually on phone but need a computer to dive in), then it just goes down the memory hole. I’ve tried setting reminders but it’s often too much fuss, and I’m far too ADHD to use a passive list.

- Exploring building yet another FE build tool/bundler that’s explicitly multi-stage/sequential with static input/output validation, per-step/time travel debugging. Motivation is that existing tools are just a big ball of config magic and totally inscrutable. I’d likely wrap existing build tools because their set of responsibilities isn’t my motivation and I don’t want to introduce that much more new API surface area to weary FE devs.

[1]: https://github.com/natemoo-re/microsite

[2]: https://github.com/callstack/linaria

[3]: https://github.com/gcanti/io-ts

Happened to me This helps me with it at the cost of a little bit more lines of code https://github.com/gcanti/io-ts
TypeScript checks that the types are correct at compile time.

If you are strict, don’t intentionally try to outsmart the type system, and use manual runtime type checking when necessary [0], TypeScript does a good practical job of ensuring that you won’t run into runtime type errors.

The reason TypeScript doesn’t automatically include runtime type information is (probably) because the overhead of runtime type checking would outweigh the benefit when static type checking does a good enough job.

Also, JavaScript being a dynamic language has allowed some pretty complex patterns of types to emerge from real-world use cases that would be exhausting to enforce all the time at runtime. Typically in TypeScript, runtime type checking is (manually) done when the type system cannot otherwise confidently guarantee the type of a value. For example, it’s common to have a runtime check for the shape of a JSON api response because you’re not necessarily in control of what that will actually return. There are community supported packages to help make this easier [1].

0: https://www.typescriptlang.org/docs/handbook/advanced-types....

1: https://github.com/gcanti/io-ts

I will only nitpick on the part about TypeScript not being type-safe enough, where extra fields are possible or wrong types can be sent over the wire.

io-ts [0] completely solves this issue, to the point where I don't think it's less type-safe than Rust in any practical manner. I've been writing apps in TS this way for the past year and I have quite a large codebase in production. The errors you mention do not happen.

[0] - https://github.com/gcanti/io-ts

Instead of ts-runtime, use io-ts (https://github.com/gcanti/io-ts). That one is actually maintained, unlike ts-runtime!
That’s where you use something like https://github.com/gcanti/io-ts to enforce types on unknown data at runtime.
You might find io-ts [1] interesting. It allows to write composable parsers that do both runtime checks and have correct result types.

Opt-in runtime checks for SQL queries are also on the roadmap for PgTyped. You are welcome to open an issue to track our progress there if you think this feature will be useful for you.

[1] https://github.com/gcanti/io-ts

Then why not use libraries like io-ts [0] to define interfaces, which survive the compilation, can test untyped objects against the given schema and could also be used as DI tokens. Still, depending on structural typing here feels like a hack, but I never did this so maybe someone with experience in a large codebase can chime in.

Anyway, IMHO, Typescript isn't designed for dependency injection in mind. Microsoft also has a DI library [1] but it feels like too much wiring to compensate for the lack of compiled interfaces.

[0]: https://github.com/gcanti/io-ts

[1]: https://github.com/Microsoft/tsyringe

> Perhaps if TS or an extension allowed "materializing" TS, that is `value instanceof SomeInterface` generated code to check for the existence of appropriate interface members, this could be avoided

It's not perfect and a bit of a bolt-on, but io.ts works reasonably well in this area:

https://github.com/gcanti/io-ts

I've used a few similar libraries [0][1][2] and wrote one for a personal project. If we categorize them as embedded DSLs for runtime type checking with some support for static interop, they all share three major flaws:

1. Sub-optimal developer experience: significantly noisier syntax compared to pure typescript, convoluted typescript errors, and slower type checking.

2. Unfixable edge cases in static type checking: Features like conditional types work less reliably on the types produced by the library.

3. Some typescript features can't be supported in the library (again, conditional types).

I think a better way to approach the runtime+static type checking is to do it as a babel plugin, which would fix the DX and edge-case problems and also gracefully degrade in the case of typescript features that can't work in runtime.

Since babel can now parse typescript, it is trivial to write a babel plugin that takes regular typescript files and converts their type annotations into runtime values [4]. Those values can then be fed into a simpler type checking library, giving us runtime type checking on top of the native static type checking experience.

[0] https://github.com/gcanti/io-ts

[1] https://github.com/pelotom/runtypes

[2] mobx-state-tree also has a schema validation library that works to some extent statically: https://github.com/mobxjs/mobx-state-tree/

[3] https://github.com/gcanti/io-ts#branded-types--refinements

[4] https://gist.github.com/AriaMinaei/2f1229178abad4363f5180db2...

Since Typescript is mentioned, might as well mention the awesome io-ts[1] library. It gives you both runtime validation and static type safety with very simple syntax.

[1]: https://github.com/gcanti/io-ts

Pattern matching is definitely something I also miss. For input validation and Optional/Either types, io-ts/fp-ts (https://github.com/gcanti/io-ts) fulfill my needs perfectly, especially io-ts is something I can't recommend enough. Saved me so many headaches from sudden breaking changes in APIs we consume.