ts-json-schema-generator
ts-json-schema-generator copied to clipboard
Incorrect output for intersection of records with the same property
This
type Schema = {
a: {
b: any
}
} & {
a: {
c: any
}
};
yields this:
{
"$schema": "http://json-schema.org/draft-07/schema#",
"$ref": "#/definitions/Schema",
"definitions": {
"Schema": {
"type": "object",
"additionalProperties": false,
"properties": {
"a": {
"type": "object",
"properties": {
"b": {}
},
"required": [
"b"
],
"additionalProperties": false
}
},
"required": [
"a"
]
}
}
}
The c property is missing.
Looks like we are not recursively merging key types here. Good catch. Do you want to take a stab at a pull request?
Frankly, if I were to try to fix this myself, I don't know where I'd begin to look, nor what I'd do once I find what I'm looking for. I'm not in the slightest familiar with how this package works.
Basically, the library consists of a parser stage and then a generator stage. One starting point could be the intersection node parser https://github.com/vega/ts-json-schema-generator/blob/next/src/NodeParser/IntersectionNodeParser.ts.
What I would do is create a failing test case, debug the test case, and step through the code. https://astexplorer.net/ is great for understanding what type of AST node you have and where to put a breakpoint.
Thanks! I'll take a look when I can.
I've definitely found the cause of the issue. It's in https://github.com/vega/ts-json-schema-generator/blob/next/src/Utils/deepMerge.ts. This screenshot alone should have all of the information necessary to see what's wrong.

Based on the values of the variables on the left sidebar, you can see the loop is just going to end and the entire function will return a shallow clone of b in this case, leaving the contents of a completely unused.
I don't really know where to go from here since I don't understand what the intention, scope, or usage of deepMerge is supposed to be. It clearly isn't meant to be just a function that deep-merges two arbitrary objects. Either that or there was a huge mistake in its implementation, because it doesn't do any deep merging at all--only shallow merging on line 18.
In fact, the function isn't even called recursively under any circumstance. Though I did find this old commit which removed functionality in which it was. And what do you know, I downloaded the repo from before that commit, and this issue doesn't occur in it (though the output is different in other ways, as you would expect from a much older version of the package). After that commit, it's broken again.
Irrelevant but still worth noting: this function's comment documents an intersectArrays parameter, but no such parameter exists on the function.
That same breaking commit also removed a deepMerge test for it("merges objects", ...). Not sure why. That test should probably be added again; it seems to be relevant here. (Though perhaps completely differently from the way it was before.)
https://github.com/vega/ts-json-schema-generator/blob/2a8af9c1f290916aac76aa28cc96097c32ee5fa4/test/unit/deepMerge.test.ts#L39-L52
Nice find. Of course I don't remember what I was thinking two years ago. I think I was fixing something around enums.
Let's try bringing the deep merge logic back.
Alright! Let me know how that goes :)
It's worth noting that the original version didn't merge arrays correctly, at least in this case. The required array would be empty rather than containing both "b" and "c".
What's the status on this?
Latest status is what's in this issue. I don't have the cycles to fix this unfortunately. Pull requests are very welcome.
Oh okay, I asked because I was under the impression you were still trying to fix it yourself. Was wondering if you ran into complications or something.