`anyOf` just for `required` gives unknown
leomp12 opened this issue · 2 comments
About
anyOf
may be used on objects to define at least one of these properties is required, but not all of them at the same time, in this case anyOf
will be an array of objects with only the required
property: Array<{ required: string[] }>
. In this case the object properties
seems to be being ignored and json2ts outputs { [k: string]: unknown; }[]
.
I think anyOf
should be ignored if it's an array of objects with only the required
property.
Or some parameter to force ignore
anyOf
?
Example
The following schema:
{
"type": "object",
"definitions": {
"picture_size": {
"type": "object",
"required": [
"url"
],
"additionalProperties": false,
"properties": {
"url": {
"type": "string",
"maxLength": 255,
"format": "uri",
"description": "Image link"
},
"size": {
"type": "string",
"maxLength": 11,
"pattern": "^[1-9]([0-9]+)?x[1-9]([0-9]+)?$",
"description": "Image size (width x height) in px, such as 100x50 (100px width, 50px height)"
},
"alt": {
"type": "string",
"maxLength": 255,
"description": "Alternative text, HTML alt tag (important for SEO)"
}
},
"description": "Image size variant"
}
},
"properties": {
"pictures": {
"type": "array",
"maxItems": 50,
"items": {
"type": "object",
"additionalProperties": false,
"anyOf": [
{
"required": [
"normal"
]
},
{
"required": [
"big"
]
},
{
"required": [
"zoom"
]
}
],
"dynamicDefaults": {
"_id": "objectId"
},
"properties": {
"_id": {
"type": "string",
"pattern": "^[a-f0-9]{24}$",
"description": "Picture ID (ObjectID) [auto]"
},
"tag": {
"type": "string",
"maxLength": 20,
"pattern": "^[a-z0-9_]+$",
"description": "Tag to identify object, use only lowercase letters, digits and underscore"
},
"normal": {
"$ref": "#/definitions/picture_size",
"description": "Default image size variant"
},
"big": {
"$ref": "#/definitions/picture_size",
"description": "Image big size variant"
},
"zoom": {
"$ref": "#/definitions/picture_size",
"description": "Image zoom size variant"
},
"small": {
"$ref": "#/definitions/picture_size",
"description": "Image small size variant"
}
},
"description": "Image object"
},
"description": "List of product images"
}
}
}
Is compiled to:
export interface Products {
pictures?: (
| {
[k: string]: unknown;
}
| {
[k: string]: unknown;
}
| {
[k: string]: unknown;
}
)[];
}
Removing the anyOf
it's correctly compiled to:
export interface Products {
pictures?: {
/**
* Picture ID (ObjectID) [auto]
*/
_id?: string;
/**
* Tag to identify object, use only lowercase letters, digits and underscore
*/
tag?: string;
normal?: PictureSize;
big?: PictureSize1;
zoom?: PictureSize2;
small?: PictureSize3;
}[];
}
/**
* Default image size variant
*/
export interface PictureSize {
/**
* Image link
*/
url: string;
/**
* Image size (width x height) in px, such as 100x50 (100px width, 50px height)
*/
size?: string;
/**
* Alternative text, HTML alt tag (important for SEO)
*/
alt?: string;
}
/**
* Image big size variant
*/
export interface PictureSize1 {
/**
* Image link
*/
url: string;
/**
* Image size (width x height) in px, such as 100x50 (100px width, 50px height)
*/
size?: string;
/**
* Alternative text, HTML alt tag (important for SEO)
*/
alt?: string;
}
/**
* Image zoom size variant
*/
export interface PictureSize2 {
/**
* Image link
*/
url: string;
/**
* Image size (width x height) in px, such as 100x50 (100px width, 50px height)
*/
size?: string;
/**
* Alternative text, HTML alt tag (important for SEO)
*/
alt?: string;
}
/**
* Image small size variant
*/
export interface PictureSize3 {
/**
* Image link
*/
url: string;
/**
* Image size (width x height) in px, such as 100x50 (100px width, 50px height)
*/
size?: string;
/**
* Alternative text, HTML alt tag (important for SEO)
*/
alt?: string;
}
Whittling your example down a bit, the bug is:
Input
{
"title": "Example Schema",
"type": "object",
"anyOf": [
{
"required": "a"
},
{
"required": "b"
}
],
"properties": {
"a": {
"type": "string"
},
"b": {
"type": "string"
}
},
"additionalProperties": false
}
Output (actual)
export type ExampleSchema = ExampleSchema1 & ExampleSchema2;
export type ExampleSchema1 = {
[k: string]: unknown;
};
export interface ExampleSchema2 {
a?: string;
b?: string;
}
Output (expected)
export type ExampleSchema = ExampleSchema1 & ExampleSchema2;
export type ExampleSchema1 = {a: string} | {b: string};
export interface ExampleSchema2 {
a?: string;
b?: string;
}
Similar situation is in a schema with multiple formats for one attribute.
Example
{
type: 'object',
properties: {
date: {
type: 'string',
anyOf: [{ format: 'date' }, { format: 'date-time' }],
},
},
}
Output (expected)
date: string;
Output (actual)
date: {
[k: string]: unknown;
} & string;
Practically, such schemas work fine in e.g., ajv.
There seems to be a workaround for this specific situation. Code below works fine.
Workardound
{
type: 'object',
properties: {
date: {
anyOf: [
{ type: 'string', format: 'date' },
{ type: 'string', format: 'date-time' },
],
},
},
}