Open
Description
When modeling inheritance, we can use $ref
to point to an existing definition and extend it.
e.g.:
{
"$schema": "https://json-schema.org/draft/2020-12/schema",
"title": "Sample",
"type": "object",
"additionalProperties": false,
"properties": {
"neighborhood": {
"type": "array",
"items": {
"$ref": "#/$defs/person"
}
}
},
"$defs": {
"baseType": {
"title": "BaseType",
"type": "object",
"properties": {
"name": {
"type": "string"
}
}
},
"person": {
"title": "Person",
"$ref": "#/$defs/baseType",
"type": "object",
"unevaluatedProperties": false,
"properties": {
"age": {
"type": "number"
}
}
}
}
}
and the expected output to be equivalent to:
export interface Sample {
neighborhood?: Person[];
}
export interface Person extends BaseType {
age?: "number";
}
export interface BaseType {
name?: string;
}
But with the provided code, the output of json-schema-to-typescript
(14.1) with default options will be erroneous:
- There won't be any type generated for
BaseType
even if it's "reachable" - Properties from
BaseType
will be missing inPerson
Person
object can have extra properties even thoughunevaluatedProperties
is set to false
Here is the generated output with the default settings:
export interface Sample {
neighborhood?: Person[];
}
export interface Person {
age?: "number";
[k: string]: unknown;
}
Even by enabling unreachableDefinitions
, the output isn't better. BaseType
appears but it's still not used properly.
export interface Sample {
neighborhood?: Person[];
}
export interface Person {
age?: "number";
[k: string]: unknown;
}
/**
* This interface was referenced by `Sample`'s JSON-Schema
* via the `definition` "baseType".
*/
export interface BaseType {
name?: string;
[k: string]: unknown;
}
/**
* This interface was referenced by `Sample`'s JSON-Schema
* via the `definition` "person".
*/
export interface Person1 {
age?: "number";
[k: string]: unknown;
}
The closest schema that would produce something close to the expected result would be:
{
"$schema": "https://json-schema.org/draft/2020-12/schema",
"title": "Sample",
"type": "object",
"additionalProperties": false,
"properties": {
"neighborhood": {
"type": "array",
"items": {
"$ref": "#/$defs/person"
}
}
},
"$defs": {
"baseType": {
"title": "BaseType",
"type": "object",
"properties": {
"name": {
"type": "string"
}
}
},
"person": {
"title": "Person",
"type": "object",
"allOf": [
{ "$ref": "#/$defs/baseType" },
{
"properties": {
"age": {
"type": "number"
}
},
"unevaluatedProperties": false
}
]
}
}
}
Edit: I removed a part I was talking about using additionalProperties
to store the $ref but I was mistaken, it's not the same behavior.