ts-json-schema-generator
ts-json-schema-generator copied to clipboard
Don't output intermediate aliases
export interface Parent {
a: A;
}
export type A = RealA;
export type RealA = { realA: string };
./node_modules/.bin/ts-json-schema-generator \
--path 'test.ts' \
--type 'Parent' \
--expose 'export' \
--jsDoc 'extended'
outputs
{
"$ref": "#/definitions/Parent",
"$schema": "http://json-schema.org/draft-06/schema#",
"definitions": {
"A": {
"$ref": "#/definitions/RealA"
},
"Parent": {
"additionalProperties": false,
"properties": {
"a": {
"$ref": "#/definitions/A"
}
},
"required": [
"a"
],
"type": "object"
},
"RealA": {
"additionalProperties": false,
"properties": {
"realA": {
"type": "string"
}
},
"required": [
"realA"
],
"type": "object"
}
}
}
However, if RealA is not referred elsewhere, it's better to output:
{
"$ref": "#/definitions/Parent",
"$schema": "http://json-schema.org/draft-06/schema#",
"definitions": {
"A": {
"additionalProperties": false,
"properties": {
"realA": {
"type": "string"
}
},
"required": [
"realA"
],
"type": "object"
},
"Parent": {
"additionalProperties": false,
"properties": {
"a": {
"$ref": "#/definitions/A"
}
},
"required": [
"a"
],
"type": "object"
}
}
}
Note that this is quite important to make the schema legible. (It will reduce number of stacks in JSON schema validation error.)
So the idea is to never output something of the form
"XXXX": {
"$ref": "#/definitions/YYYY"
}
and replace all occurrences of XXXX with YYYY
This works as expected. We output intermediate aliases when they are exported.
You can hide a alias by not exporting it:
export interface Parent {
a: A;
}
export type A = RealA;
type RealA = { realA: string };
I think only exporting types that are used more than once is going to be more surprising (and hard to implement).
Well, in Vega-Lite use case, we need the intermediate ones because RealA is generic and A is an alias for a specific form of generic.
Thus, we can't really avoid exporting the generic.
Hmm, I guess we could use the @hide annotation here to skip aliases. I don't think hiding an alias that's only used once is a good idea since it may be desired by the developer.
FWIW, adding @hide to RealA currently doesn't skip aliases.
Yep, we only respect @hide for properties right now. I suggest that we also use it to ignore aliases. Would that be the solution that we want?
I guess that sounds good to me.
I don't know if/how @hide currently works for aliases at all.
It doesn't. We only use it for properties of objects and interfaces.
and interfaces
Oh well, it's worth noting that we actually want to keep the alias and hide the original interface.
Like hiding RealA and keep only A in the example above.
But more practical use case is to think if we have GenericA<T> and type A = Generic<string>, then we want to only keep A.
I don't think hiding an alias that's only used once is a good idea since it may be desired by the developer.
I'd argue that in most cases, there is no good reason for the developer to want to keep the chaining since "an alias that's only used once" means that all references of the original interface is called via the alias, but the schema simply treat the alias as chaining more than real "alias".