-
Notifications
You must be signed in to change notification settings - Fork 216
Description
The combination of an intersected type and type transform (e.g. any TypeScript Utility Type),
can cause compilation to incorrect object type,
on any non-primitive (e.g. Array, Tuple) child properties.
type Intersected = {
/** Array of vertex indices. */
v: number[];
} & {};
export type Transformed = Required<Intersected>compiles to incorrect json schema:
{
"$schema": "http://json-schema.org/draft-07/schema#",
"$ref": "#/definitions/B",
"definitions": {
"Transformed": {
"type": "object",
"properties": {
"v": {
"type": "object",
"properties": {},
"description": "Array of vertex indices.",
},
},
"additionalProperties": false,
},
},
}It appears to be only the combination of the intersected type and the type
transform that causes this issue. If you remove either, schema generation is
correct:
export type Intersected = {
/** Array of vertex indices. */
v: number[];
} & {};
type NonIntersected = {
/** Array of vertex indices. */
v: number[];
};
export type Transformed = Required<NonIntersected>generates correct json schema:
{
"$schema": "http://json-schema.org/draft-07/schema#",
"definitions": {
"Intersected": {
"type": "object",
"properties": {
"v": {
"type": "array",
"items": {
"type": "number",
},
"description": "Array of vertex indices.",
},
},
"required": [ "v" ],
},
"Transformed": {
"type": "object",
"properties": {
"v": {
"type": "array",
"items": {
"type": "number",
},
"description": "Array of vertex indices.",
},
},
},
},
}Also, if the child property type is a primitive, the issue does not occur:
type Intersected = {
v: number;
} & {};
export type Transformed = Required<Intersected>generates correct json schema:
{
"$schema": "http://json-schema.org/draft-07/schema#",
"$ref": "#/definitions/Transformed",
"definitions": {
"Transformed": {
"type": "object",
"properties": {
"v": {
"type": "number",
},
},
"additionalProperties": false,
},
},
}Clues
Interestingly, if we remove the jsdoc comment, we get a generated schema that
may provide some insight into what is happening:
type Intersected = {
v: number[]; // no jsdoc comment
} & {};
export type Transformed = Required<Intersected>compiles to:
{
"$schema": "http://json-schema.org/draft-07/schema#",
"$ref": "#/definitions/Transformed",
"definitions": {
"Transformed": {
"type": "object",
"properties": {
"v": {
"allOf": [
{
"type": "array",
"items": {
"type": "number",
},
}, {
"type": "object",
"properties": {},
}
],
},
},
"additionalProperties": false,
},
},
}It appears to be intersecting the child property with an empty object
(instead of the parent).
Repro
const config: Config = {
...DEFAULT_CONFIG,
additionalProperties: true,
path: "test.ts", // above examples
skipTypeCheck: true,
tsconfig: "tsconfig.json", // identical to the one used by the `ts-json-schema-generator` package
};
const schema = createGenerator(config).createSchema(config.type);