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 in Person
Person object can have extra properties even though unevaluatedProperties 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.
When modeling inheritance, we can use
$refto 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:
But with the provided code, the output of
json-schema-to-typescript(14.1) with default options will be erroneous:BaseTypeeven if it's "reachable"BaseTypewill be missing inPersonPersonobject can have extra properties even thoughunevaluatedPropertiesis set to falseHere is the generated output with the default settings:
Even by enabling
unreachableDefinitions, the output isn't better.BaseTypeappears but it's still not used properly.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
additionalPropertiesto store the $ref but I was mistaken, it's not the same behavior.