json-schema-to-typescript icon indicating copy to clipboard operation
json-schema-to-typescript copied to clipboard

Cannot pass JSONSchema7 schema to compile as it requires JSONSchema4

Open G-Rath opened this issue 3 years ago • 8 comments

Currently the types are using JSONSchema4 as the type for schema, which means TypeScript won't let you pass objects of type JSONSchema7 due to type differences.

Specifically, exclusiveMaximum & exclusiveMinimum are typed as boolean | undefined in JSONSchema4, but as number | undefined in JSONSchema7. (there probably are more differences - I've not compared the two further than that).

I think the right type to use would be a union of the different schemas supported, i.e JSONSchema7 | JSONSchema4.

G-Rath avatar Dec 23 '20 20:12 G-Rath

If there's an exhaustive comparison of JSONSchema 4 vs. 6 vs. 7 somewhere, that could help us pick a path forward:

  • Find a way to type everything as a union of what's supported by 4, 6, and 7?
  • Convert all input schemas to 7 before processing them?
  • Create version-specific adapters when versions diverge, and sharing logic when they're the same?

bcherny avatar Dec 27 '20 23:12 bcherny

I don't think the difference between schema versions is wide enough that it'd affect what ts types to generate, at least for versions up to 7, so I think it's best to keep things simple: ultimately, json-schema-to-typescript takes in an object and generated types based on it's properties - whether a property is "allowed" in that object doesn't matter for type generation.

I think the first step should be to create a JSONSchema union type of JSONSchema4 | JSONSchema6 | JSONSchema7, and see what TypeScript says - if there are no unexpected errors I think that should be fine to ship. I'm happy to do a PR for this if you agree.

After that I think is where your comment comes into play: how should keywords introduced in later json schemas (i.e const) be supported?

Personally I think it should be fine to just implement support for the new properties as-is, without version detecting - const is the main one that comes to mind, and I doubt people would have a property in their old-version schemas for that.

G-Rath avatar Dec 28 '20 00:12 G-Rath

I've had a look at the types for json-schema-to-typescript and see now it'll be a bit more work than just simply unioning the three schema version types together due to the number of interfaces that extend from JSONSchema (since extending can't be done on a union).

This actually makes things a lot more complicated as JSONSchema 7 dropped support for the any type, which json-schema-to-typescript can and does check for.

Personally as an immediate solution I vote for changing the signature of compile to take JSONSchema4 | JSONSchema6 | JSONSchema7 and cast the schema to JSONSchema4 when passing it to validate.

G-Rath avatar Dec 28 '20 01:12 G-Rath

I had a design requirement that made me apply const, thus upgrade to JSONSchema6 as well.

and see now it'll be a bit more work than just simply unioning the three schema version types together due to the number of interfaces that extend from JSONSchema

however, if this lib is to support each, isn't this precisely what the lib would need to do? common attrs should work fine, but for non-intersecting keys, "key" in schema checks would be required to narrow the types and execute version/version-range specific functionality.

cdaringe avatar Jan 04 '21 03:01 cdaringe

Lots of great input. As I suggested earlier, does someone want to start by auditing JSONSchema 4 vs. 6 vs. 7 to see what’s new, and what’s backwards-incompatible? Publishing the audit as a table in this task could be a great start to understand the right way forward.

bcherny avatar Jan 04 '21 05:01 bcherny

Just found this package and am amazed at how useful it is! But I am also running into the issue of the types not being compatible between JSONSchema7 and what this package expects JSONSchema4.

coryjamescrook avatar Feb 10 '21 21:02 coryjamescrook

Lots of great input. As I suggested earlier, does someone want to start by auditing JSONSchema 4 vs. 6 vs. 7 to see what’s new, and what’s backwards-incompatible? Publishing the audit as a table in this task could be a great start to understand the right way forward.

There is a comparison table on the json-schema.org web-site, here is a direct link to it: https://json-schema.org/draft-06/json-schema-release-notes.html. I'll copy the table here:

draft v4 vs v6

Backwards-incompatible changes:

keyword change consequence
"id" replaced by "$id" no longer easily confused with instance properties named "id"
"$id" replaces "id" behavior is identical, $ prefix matches the other two core keywords
"$ref" only allowed where a schema is expected it is now possible to describe instance properties named "$ref"
"exclusiveMinimum" and "exclusiveMaximum" changed from a boolean to a number to be consistent with the principle of keyword independence wherever one of these would be true before, change the value to the corresponding "minimum" or "maximum" value and remove the "minimum"/"maximum" keyword
"type" definition of "integer" in draft-04, "integer" is listed as a primitive type and defined as “a JSON number without a fraction or exponent part”; in draft-06, "integer" is not considered a primitive type and is only defined in the section for keyword "type" as “any number with a zero fractional part”; 1.0 is thus not a valid "integer" type in draft-04 and earlier, but is a valid "integer" type in draft-06 and later; note that both drafts say that integers SHOULD be encoded in JSON without fractional parts

Additions and backwards-compatible changes:

keyword change consequence
booleans as schemas allowable anywhere, not just "additionalProperties" and "additionalItems" true is equivalent to {}, false is equivalent to {"not": {}}, but the intent is more clear and implementations can optimize these cases more easily
"propertyNames" added takes a schema which validates the names of all properties rather than their values
"contains" added array keyword that passes validation if its schema validates at least one array item
"const" added more readible form of a one-element "enum"
"required" allows an empty array an empty array indicates that no properties are required
"dependencies" allows an empty array for property dependencies an empty array indicates that there are no dependencies for the given property
"format": "uri-reference" added allows relative URI references per RFC 3986; see the section below about "uri" as a format
"format": "uri-template" added indicates an RFC 6570 conforming URI Template value, as is used in JSON Hyper-Schema for "href"
"format": "json-pointer" added indicates a JSON Pointer value such as /foo/bar; do not use this for JSON Pointer URI fragments such as #/foo/bar: the proper format for those is "uri-reference"
"examples" added array of examples with no validation effect; the value of "default" is usable as an example without repeating it under this keyword

draft v6 vs v7

From json-schema.org web-site: For the Core and Validation specifications, draft-07 is a relatively minor update. In terms of validation keywords and outcomes, it is fully backwards-compatible with draft-06.

Direct link to draft v7 release notes: https://json-schema.org/draft-07/json-schema-release-notes.html

valcker avatar Feb 24 '21 15:02 valcker

Adding support for the dependencies would be great. Currently, the attributes defined inside there are not generated at all.

DanielHabenicht avatar Mar 13 '21 14:03 DanielHabenicht