Skip to content

Commit a20099b

Browse files
committed
Fixes YousefED#107 by manually merging the objects into one.
1 parent 79e29aa commit a20099b

File tree

3 files changed

+51
-32
lines changed

3 files changed

+51
-32
lines changed
+12-29
Original file line numberDiff line numberDiff line change
@@ -1,43 +1,26 @@
11
{
2-
"type": "object",
2+
"$schema": "http://json-schema.org/draft-04/schema#",
3+
"additionalProperties": false,
34
"properties": {
45
"value": {
5-
"allOf": [
6-
{
7-
"$ref": "#/definitions/Type1"
8-
},
9-
{
10-
"$ref": "#/definitions/Type2"
11-
}
12-
]
13-
}
14-
},
15-
"required": [
16-
"value"
17-
],
18-
"definitions": {
19-
"Type1": {
20-
"type": "object",
6+
"additionalProperties": false,
217
"properties": {
228
"value1": {
239
"type": "string"
24-
}
25-
},
26-
"required": [
27-
"value1"
28-
]
29-
},
30-
"Type2": {
31-
"type": "object",
32-
"properties": {
10+
},
3311
"value2": {
3412
"type": "number"
3513
}
3614
},
3715
"required": [
16+
"value1",
3817
"value2"
39-
]
18+
],
19+
"type": "object"
4020
}
4121
},
42-
"$schema": "http://json-schema.org/draft-04/schema#"
43-
}
22+
"required": [
23+
"value"
24+
],
25+
"type": "object"
26+
}

test/schema.test.ts

+3-1
Original file line numberDiff line numberDiff line change
@@ -147,7 +147,9 @@ describe("schema", () => {
147147
*/
148148

149149
assertSchema("type-union", "main.ts", "MyObject");
150-
assertSchema("type-intersection", "main.ts", "MyObject");
150+
assertSchema("type-intersection", "main.ts", "MyObject", {
151+
disableExtraProperties: true
152+
});
151153
assertSchema("type-union-tagged", "main.ts", "Shape");
152154
assertSchema("type-aliases-union-namespace", "main.ts", "MyModel");
153155

typescript-json-schema.ts

+36-2
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,28 @@ export type Definition = {
7777
typeof?: "function"
7878
};
7979

80+
function extend(target: any, ..._: any[]) {
81+
if (target == null) { // TypeError if undefined or null
82+
throw new TypeError("Cannot convert undefined or null to object");
83+
}
84+
85+
const to = Object(target);
86+
87+
for (var index = 1; index < arguments.length; index++) {
88+
const nextSource = arguments[index];
89+
90+
if (nextSource != null) { // Skip over if undefined or null
91+
for (const nextKey in nextSource) {
92+
// Avoid bugs when hasOwnProperty is shadowed
93+
if (Object.prototype.hasOwnProperty.call(nextSource, nextKey)) {
94+
to[nextKey] = nextSource[nextKey];
95+
}
96+
}
97+
}
98+
}
99+
return to;
100+
}
101+
80102
export class JsonSchemaGenerator {
81103
/**
82104
* JSDoc keywords that should be used to annotate the JSON schema.
@@ -667,10 +689,22 @@ export class JsonSchemaGenerator {
667689
if (typ.flags & ts.TypeFlags.Union) {
668690
this.getUnionDefinition(typ as ts.UnionType, prop!, tc, unionModifier, definition);
669691
} else if (typ.flags & ts.TypeFlags.Intersection) {
670-
definition.allOf = [];
692+
// extend object instead of using allOf because allOf does not work well with additional properties. See #107
693+
if (this.args.disableExtraProperties) {
694+
definition.additionalProperties = false;
695+
}
696+
671697
const types = (<ts.IntersectionType> typ).types;
672698
for (let i = 0; i < types.length; ++i) {
673-
definition.allOf.push(this.getTypeDefinition(types[i], tc));
699+
const other = this.getTypeDefinition(types[i], tc, false);
700+
definition.type = other.type; // should always be object
701+
definition.properties = extend(definition.properties || {}, other.properties);
702+
if (Object.keys(other.default || {}).length > 0) {
703+
definition.default = extend(definition.default || {}, other.default);
704+
}
705+
if (other.required) {
706+
definition.required = (definition.required || []).concat(other.required);
707+
}
674708
}
675709
} else if (isRawType) {
676710
this.getDefinitionForRootType(typ, tc, reffedType!, definition);

0 commit comments

Comments
 (0)