Hacker Newsnew | past | comments | ask | show | jobs | submitlogin

Ok since we have a lot of TS people here maybe someone can help me out.

Let's say I have a simple interface with a few fields. I want to make sure incoming JSON conforms to that interface.

I realize at runtime the interface isn't there, but is there some tool I can use to compile a utility to check JSON against an interface without having to write a duplicative JSONSchema or something else?



io-ts [1] is what I think most people use for this

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


Personally I dislike the fact that io-ts requires taking a pure functional programming approach to this validation. For most cases I just want to throw an error if something doesn't match up. My main use case for this is validating that my UI and backend API have the same ideas about the shape of the data, which will either always work or always fail. All errors should be caught during development and testing, so the "either" case will never realistically be hit in production.

Because of this I prefer runtypes [1], because it's much more simple to get my desired behavior. My only gripe is that errors aren't all that descriptive.

I guess I could write a function to pipe/fold into the type, throwing a descriptive error if something fails, but I like the simplicity of runtypes.

Edit: I just discovered io-ts ErrorReporter [2]. That's way better than my solution, and I'm considering switching now!

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

2: https://github.com/gcanti/io-ts/blob/master/src/ThrowReporte...


We wrote a bunch of utility methods around io-ts at work with custom error reporting/handling, otherwise it can indeed feel a bit too fp-/boilerplate-heavy for your every day frontend development, especially in combination with other stuff such as rxjs/redux.

But once you have those set up, it's an easy breeze, and the benefits are enormous. Our helper-method with the hopefully self-explanatory name "validateOrThrow<T>(t:TypeGuardForT)" is essentially called at every point where there is some form of incoming external data, and the amount of debugging-headaches that have simply disappeared because of this is mind-blowing.


My advice is bite the bullet and just write a JSON Schema for the interface and use ajv[1] to check it. Keep the interface, the JSON Schema, and the validator function (which should be a type guard[2] to take full advantage of TypeScript) in the same module for easier maintenance.

[1] https://github.com/epoberezkin/ajv

[2] https://www.typescriptlang.org/docs/handbook/advanced-types....


I am having the same problem and I think I am going to go with json schema.

The problem is that a lot of the things you want to validate aren't easily expressible as typescript types (e.g., valid email address, make sure two fields are always the same length, etc). If json schema are more expressive you want to use that as your source to generate the typescript interface instead of the other way around.


I solved this using the ts-interface-builder and ts-interface-checker libraries and have been happy with the result. You write a plain TS type (rather than a custom syntax like io-ts has) and then run a codegen step to make a runtime representation of the type. Then you can create a checker from that and do runtime type checking.

https://github.com/gristlabs/ts-interface-builder

https://github.com/gristlabs/ts-interface-checker

Example: https://github.com/alangpierce/sucrase/pull/468/files


I had the same problem and used a JSONSchema as a single source of truth. Then from that schema you can generate:

- the typescript interfaces: https://www.npmjs.com/package/json-schema-to-typescript

- the runtime checks with AJV

So you have no duplication and you're type safe.


We use TSOA[1] for that, it can build OpenApi specification from your ts interface. So its could be used for documentation and tsoa can validate but other tools can validate too

[1] https://github.com/lukeautry/tsoa


I’d suggest generating code

Write your interface in json or text proto then build it to ts interfaces and runtime checks.


Agree with the code generation approach. Otherwise you need to make sure the annotations are in sync with the type / class / interface.

Typescript doesn't support macro currently, so code generation is the only way to programmatically create 'type-checked' code.

Some cli-tool and library I'm using (available on npm):

tsc-macro: https://github.com/beenotung/tsc-macro

gen-ts-type: https://github.com/beenotung/gen-ts-type

ts-type-check: https://github.com/beenotung/ts-type-check


I wrote a tool that may be useful here; it generates a TypeScript definition file and runtime type checking logic given examples of the objects you want to accept.

https://jvilk.com/MakeTypes/


I've used typescript-json-schema to generate a schema based on an interface. I had a script that could regenerate the schema, and a CI script that ran ajv on a set of fixture JSON files to ensure any schema changes were backward-compatible.


ts-json-schema-generator[1] generates a schema from an annotated interface definition.

[1] https://github.com/vega/ts-json-schema-generator




Consider applying for YC's Summer 2026 batch! Applications are open till May 4

Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: