diff --git a/packages/specs/schema/src/decorators/common/nullable.spec.ts b/packages/specs/schema/src/decorators/common/nullable.spec.ts index 11a25ad13e7..23506f760be 100644 --- a/packages/specs/schema/src/decorators/common/nullable.spec.ts +++ b/packages/specs/schema/src/decorators/common/nullable.spec.ts @@ -1,4 +1,4 @@ -import {Nullable, Property, Required} from "@tsed/schema"; +import {Nullable, Property, Required, SpecTypes} from "@tsed/schema"; import {expect} from "chai"; import {getJsonSchema} from "../../utils/getJsonSchema"; @@ -151,4 +151,69 @@ describe("@Nullable", () => { type: "object" }); }); + it("should declare any prop (many Models + Nullable)", () => { + // WHEN + class Nested1 { + @Property() + id: string; + + @Property() + top: string; + } + + class Nested2 { + @Property() + id: string; + + @Property() + other: string; + } + + class Model { + @Nullable(Nested1, Nested2) + prop2: Nested1 | Nested2 | null; + } + + // THEN + expect(getJsonSchema(Model, {specType: SpecTypes.OPENAPI})).to.deep.equal({ + definitions: { + Nested1: { + properties: { + id: { + type: "string" + }, + top: { + type: "string" + } + }, + type: "object" + }, + Nested2: { + properties: { + id: { + type: "string" + }, + other: { + type: "string" + } + }, + type: "object" + } + }, + properties: { + prop2: { + anyOf: [ + { + $ref: "#/components/schemas/Nested1" + }, + { + $ref: "#/components/schemas/Nested2" + } + ], + nullable: true + } + }, + type: "object" + }); + }); }); diff --git a/packages/specs/schema/src/domain/JsonSchema.ts b/packages/specs/schema/src/domain/JsonSchema.ts index bbd9b890b96..68f59c675ca 100644 --- a/packages/specs/schema/src/domain/JsonSchema.ts +++ b/packages/specs/schema/src/domain/JsonSchema.ts @@ -731,13 +731,28 @@ export class JsonSchema extends Map implements NestedGenerics { } any(...types: any[]) { - types = uniq(types.length ? types : ["integer", "number", "string", "boolean", "array", "object", "null"]).map(getJsonType); + const hasClasses = types.filter((type) => isClass(type)); + + if (hasClasses.length >= 2) { + this.anyOf( + types.filter((value) => { + if (value !== null) { + this.nullable = true; + return false; + } + return true; + }) + ); + } else { + // TODO when OS3 will the only minimal supported version, we'll can remove this code + types = uniq(types.length ? types : ["integer", "number", "string", "boolean", "array", "object", "null"]).map(getJsonType); - if (types.includes("null")) { - this.nullable = true; - } + if (types.includes("null")) { + this.nullable = true; + } - this.type(types.length === 1 ? types[0] : types); + this.type(types.length === 1 ? types[0] : types); + } return this; }