You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Given a schema that contains a named definition (Level2B),
And that named definition is referenced in multiple locations,
And that named schema is also an intersection type (allOf in this example),
Then when parsed, the generated TypeScript will contain the correct reference only for the first location in which the named schema is encountered, during a depth-first traversal.
Subsequent references to the same schema will be generated as though they were only the intersection type, and not the named schema.
The current resulting TypeScript will be (comments adjusted for clarity):
// Incorrect: should be `type Demo = Level2A | Level2B`// Note that the Level2B type at this location is the _second_ instance to// Level2B during a depth-first traversal.exporttypeDemo=Level2A|Level2B1;exporttypeLevel2A=Level2A1&{// Correct in this location because this property is reached first in a// depth-first traversal.level_2A_ref?: Level2B;[k: string]: unknown;};exporttypeLevel2A1=Base;exporttypeLevel2B=Level2B1&{level_2B_prop?: "xyzzy";[k: string]: unknown;};exporttypeLevel2B1=Base;exportinterfaceBase{base_prop?: string;[k: string]: unknown;}
Root Cause
In parser.ts, lines 57 - 75, when schema that matches multiple "types" is encountered, the parser generates a new ALL_OF intersection schema to contain each sub-type, then adds each sub-type to the new ALL_OF schema.
Each sub-type is then parsed sequentially. During this process, maybeStripNameHints is called, which mutates the schema by removing the $id, description, and name properties.
Notably, these properties are used by typesOfSchema to detect the NAMED_SCHEMA type. As a result, this schema object will never again be detected as a NAMED_SCHEMA type.
Therefore, the first instance of the schema object is correctly handled as an intersection schema and a named schema, but all subsequent instances are treated as though they are only an intersection schema.
Proposed Solution
I have completed a proof-of-concept fork that addresses this:
The call to typesOfSchema is moved from parser.ts to normalizer.ts, with the goal of avoiding confusion due to a mutated schema object. The resulting list of schema types is persisted as a $types property on the schema.
The generated intersection schema is also moved from parser.ts to normalizer.ts. This is because it is advantageous to let the generated intersection schema participate in the caching mechanism (which it could not previously do, since it was generated dynamically during each encounter). Without this, multiple instances of the same schema are generated.
Hello @bcherny ! Is there anything I can do to help make progress on this? I can make changes to the PR or take a completely different approach if you prefer. I have a project that is blocked by this and I have time this week to devote to a resolution.
Level2B
),allOf
in this example),Then when parsed, the generated TypeScript will contain the correct reference only for the first location in which the named schema is encountered, during a depth-first traversal.
Subsequent references to the same schema will be generated as though they were only the intersection type, and not the named schema.
Example
Given the following schema:
The current resulting TypeScript will be (comments adjusted for clarity):
Root Cause
In
parser.ts
, lines 57 - 75, when schema that matches multiple "types" is encountered, the parser generates a newALL_OF
intersection schema to contain each sub-type, then adds each sub-type to the newALL_OF
schema.Each sub-type is then parsed sequentially. During this process,
maybeStripNameHints
is called, which mutates the schema by removing the$id
,description
, andname
properties.Notably, these properties are used by
typesOfSchema
to detect theNAMED_SCHEMA
type. As a result, this schema object will never again be detected as aNAMED_SCHEMA
type.Therefore, the first instance of the schema object is correctly handled as an intersection schema and a named schema, but all subsequent instances are treated as though they are only an intersection schema.
Proposed Solution
I have completed a proof-of-concept fork that addresses this:
The call to
typesOfSchema
is moved fromparser.ts
tonormalizer.ts
, with the goal of avoiding confusion due to a mutated schema object. The resulting list of schema types is persisted as a$types
property on the schema.The generated intersection schema is also moved from
parser.ts
tonormalizer.ts
. This is because it is advantageous to let the generated intersection schema participate in the caching mechanism (which it could not previously do, since it was generated dynamically during each encounter). Without this, multiple instances of the same schema are generated.PR to be submitted shortly.
Related Issues
$ref
inallOf
with depth of 2 is not correctly converted when multi-referenced #597The text was updated successfully, but these errors were encountered: