ajv-validator / ajv

The fastest JSON schema Validator. Supports JSON Schema draft-04/06/07/2019-09/2020-12 and JSON Type Definition (RFC8927)
https://ajv.js.org
MIT License
13.82k stars 876 forks source link

Implement a JSONDataType to make typescript conversion on json schema #1792

Open allonzy opened 3 years ago

allonzy commented 3 years ago

What version of Ajv you are you using? 8.6.4 What problem do you want to solve? I want to dynamically infer ts types from a json schema, it will reduce the need for auto-generated file or code-duplication (define your interface 2 times, one for ts, one for ajv) What do you think is the correct solution to problem? Implement a type mapper like in JTDDataType from 'ajv/dist/jtd', and update readme/doc accordingly Will you be able to implement it? Yes

epoberezkin commented 3 years ago

I am not very optimistic about the possibility of it, but please do try - it would be interesting.

JSON Schema, is general, is not aligned with TS type system - it allows expressing constraints that are not expressible in typescript type system. Also, in some cases, I think there might be more than one possible type derived from JSON Schema (can be wrong here).

Neither is a complete blocker - for the first problem, you would have to define a subset of JSON Schema that is mappable to TS types, and have this type fail on schemas outside of this subset - that actually could be useful. For the second, we will just have to make some choices...

The type name should be JSONSchemaDataType

cc @erikbrinkman

allonzy commented 3 years ago

Also, in some cases, I think there might be more than one possible type derived from JSON Schema

Well, that might be problematic, as you say choice has to be made in that case

But the other way is not, i know that jsonSchema allow complex constraints that typescript, and that's a huge part of why i'm using it, but in a developer perspective having the static type hinting and compilation error, even on a superset type is far better than having nothing at all
Starting the implementation when i can

erikbrinkman commented 3 years ago

I generally agree with @epoberezkin on all things here. I'm also not sure if there could be multiple possible types, but this exists for JTDDataType too with timestamps being interpreted as Date | string, so it's not the end of the world, even if it's not great.

My guess is you should be able to start with JTDDataType as a backbone but swap in JSON Schema structures. It seems like it could work at least for simple schemas.

There are a few risks I want to call out.

  1. type complexity: typescript has certain built-in limits around type complexity to keep it performant, and it just errors if you reach them. JTDDataType had to be altered to get it to work in those bounds, so this is a potential issue. One way to help would be to not allow refs. Their definition as part of JTDDataType makes it much more complex, and since refs in JSONSchema are even more free form, it might be better to omit them.
  2. the overloading of compile and validate: currently the validation is checked via: https://github.com/ajv-validator/ajv/blob/43d6164d46c1afbb1f40829f5208a66507af810c/lib/core.ts#L362-L365 which is a somewhat hacky way around manually specified types, but requires that the schema is valid. I think there are cases where SomeJSONSchema and SomeJTDSchema will both match. I think in those cases the type is probably also the same, but this could pose a problem. The better solution to this would be to split the signatures according to their path, but I remember discussing this briefly with @epoberezkin and they had complaints against it.

I hope this proves fruitful!