Hacker News new | ask | show | jobs
by mnahkies 1093 days ago
You should take a look at https://zod.dev/ if you haven't already - it's a library for runtime parsing that works really well for your use case.

Types are inferred from the schema though personally I like to handwrite types as well to sense check that the schema describes the type I think it does

2 comments

I’ve used zod and every other schema validator available for this. Some problems:

1. Types are not written in typescript anymore. Or you have to define them twice and manually ensure they match. ReturnType<typeof MyType> pollutes the codebase.

2. Types have to be defined in order, since they’re now consts. If you have a lot of types which embed other types, good luck determining that order by hand.

3. Recursive types need to be treated specially because a const variable can’t reference itself without some lazy evaluation mechanism.

TS could solve all of this by baking this into the language.

1. You can just use `export type Foo = z.infer<typeof fooParser>` in one place and then import Foo everywhere else, without using z.infer everywhere else

2. Use let and modify your types as new ones become available - union them with a new object that contains the new property you need

3. How often are you making recursive types?

I agree that all of this could be made easier, but zod is the best we have and great for most normal usage. The reason TS doesn't want to make this available at runtime is that it means so many changes they make will become breaking changes. Perhaps one day when there's less development on TS we'll see this get added

Including runtime checks would also have performance implications.

I really enjoyed using myzod (more performative, simple, zod) for awhile, but recently I’ve been using Typia, which is a codegen approach. I have mixed feelings about it, and from my own benchmarking it’s performance seems overstated, but the idea is sound: because we know the type, we can compile better, type-optimized serialize/deserialize functions.

As for not littering the codebase with runtime checks, it may be worth reiterating to the person above that you really should only do type determinations at the I/O edges: you parse your input, and it becomes known from then onwards. You runtime type-check your output, and its requirements propagate upwards through your program.

There aren't really "performance implications" for making an impossible thing possible.

The ability to emit a parser/verifier would not require any other runtime or affect the speed of any other code.

Pragmatically, your interest is why I was mentioning typia, which does what you are describing: opt-in parser/stringify/mock-gen codegen derived from typescript.

I think it’s reasonable enough to allow other people to focus on runtime behavior. There’s still a lot to do to model js accurately.

In my personal opinion, the ideal ts would be one where you just write regular js, and the compiler is able to check all of it for correctness implicitly. That would require runtime validators etc to be explicitly written, yes, but you could “just write js” and the correctness of your program could be proven (with guidance to make it more provably correct when it is not yet).

It's also possible -- for specific cases, probably not generally -- define your schema object as const and use type manipulation to generate "real" types automagically. Toy example here: https://github.com/andrewaylett/aylett.co.uk/blob/3fffae1bab...

This lets me run my inputs through a schema validator, and ensure that the type I'm using statically will match the schema used at runtime.