fix(schema): keep allOf-merged properties when additionalProperties: false#3058
Merged
Conversation
…alProperties: false (#1257) When merging object types from an `allOf`, IntersectionAccumulator discarded a property as soon as any other branch didn't declare that property and didn't allow additional properties. Since JSON Schema input commonly sets `additionalProperties: false` on every branch, this meant merging two or more `allOf` branches with disjoint property sets produced an empty (or partially empty) merged object instead of the union of all their properties. Fix ResolveIntersections.ts so a property known from any branch is kept in the merged object regardless of whether other branches restrict additional properties; `additionalProperties: false` still correctly disallows properties nobody declared. Added test/inputs/schema/all-of-additional-properties-false.schema with a positive fixture sample and a `.fail.enum` negative sample (invalid enum value for a property merged in from one of the allOf branches, which only fails if that property survived the merge). Verified locally: npm run build passes, npm run test:unit passes (176 tests), and QUICKTEST=true FIXTURE=schema-typescript script/test passes (exit 0), including the new fixture. CI will cover the other schema-<language> fixtures. Fixes #1257 Co-Authored-By: gpt-5.6-sol via pi <noreply@openai.com>
cjson's generated deserializer does not validate enum values, so the `.1.fail.enum.json` negative sample of the new `all-of-additional-properties-false.schema` fixture round-trips instead of being rejected, making the expected-failure assertion fail. Add the schema to the shared `skipsEnumValueValidation` list, matching the existing enum fixtures that other non-enum-validating languages already skip. Co-Authored-By: Claude <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Bug
Issue #1257: when a JSON Schema
allOfmerges branches that each setadditionalProperties: false(a very common pattern, e.g. one branch is a$refto a shared base object and the other is inline), quicktype'sTypeScript output dropped all the properties instead of merging them.
Repro:
{ "definitions": { "AmountAndFrequency": { "type": "object", "properties": { "amount": { "type": "number" }, "frequency": { "type": "string", "enum": ["Weekly", "Monthly", "Annually"] } }, "additionalProperties": false, "required": ["amount", "frequency"] }, "Income": { "allOf": [ { "$ref": "#/definitions/AmountAndFrequency" }, { "type": "object", "properties": { "type": { "type": "string", "enum": ["GrossSalaryAmount", "Overtime"] }, "description": { "type": "string" } }, "additionalProperties": false, "required": ["type"] } ] } }, "$ref": "#/definitions/Income" }Before:
After:
Root cause
IntersectionAccumulator.updateObjectPropertiesinpackages/quicktype-core/src/rewrites/ResolveIntersections.tsmerges theobject types being intersected by an
allOf. For each property name seen sofar across branches, if the current branch didn't declare that property and
didn't allow additional properties, the property was deleted from the merged
result — even though some other branch did declare it. Since JSON Schema
input in the wild very commonly sets
additionalProperties: falseon everybranch, this deleted essentially all disjoint properties, frequently leaving
an empty merged object.
Fix
A property known from any
allOfbranch is now kept in the merged objectregardless of whether another branch restricts additional properties;
additionalProperties: falsestill correctly disallows properties that nobranch declares (that behavior is untouched — only the erroneous deletion of
already-known properties was removed).
Test coverage
Added
test/inputs/schema/all-of-additional-properties-false.schema(the repro above) with:
.1.json: a positive round-trip sample with all four merged properties..1.fail.enum.json: a negative sample with an invalid enum value forfrequency, a property that's only present at all because the merge nowworks — it guards against a regression of this exact bug rather than
testing something unrelated.
Verification
npm run buildpasses.npm run test:unitpasses (176 tests).QUICKTEST=true FIXTURE=schema-typescript script/testpasses (exit 0),including the new fixture (both the positive and
.fail.enumsamples).schema-<language>fixtures were not run locally due totime/toolchain constraints; CI will validate them.
Fixes #1257
🤖 Generated with Claude Code