Comments (8)
I recommend https://astexplorer.net/ to look at what is actually defined.
from ts-json-schema-generator.
Here's a minimal repro in astexplorer.net for reference
from ts-json-schema-generator.
Thanks, that's a helpful resource!
from ts-json-schema-generator.
Hit a similar error:
.../node_modules/ts-json-schema-generator/dist/ts-json-schema-generator.js:32
throw error;
^
TypeError: Cannot read property 'getId' of undefined
at ReferenceType.getId (.../node_modules/ts-json-schema-generator/dist/src/Type/ReferenceType.js:6:26)
at ids.join.<.context.getArguments.map (.../node_modules/ts-json-schema-generator/dist/src/CircularReferenceNodeParser.js:29:78)
at Array.map (<anonymous>)
at CircularReferenceNodeParser.createCacheKey (.../node_modules/ts-json-schema-generator/dist/src/CircularReferenceNodeParser.js:29:61)
at CircularReferenceNodeParser.createType (.../node_modules/ts-json-schema-generator/dist/src/CircularReferenceNodeParser.js:13:26)
at ChainNodeParser.createType (.../node_modules/ts-json-schema-generator/dist/src/ChainNodeParser.js:17:50)
at ExpressionWithTypeArgumentsNodeParser.createType (.../node_modules/ts-json-schema-generator/dist/src/NodeParser/ExpressionWithTypeArgumentsNodeParser.js:23:41)
at ChainNodeParser.createType (.../node_modules/ts-json-schema-generator/dist/src/ChainNodeParser.js:17:50)
at AnnotatedNodeParser.createType (.../node_modules/ts-json-schema-generator/dist/src/NodeParser/AnnotatedNodeParser.js:15:47)
at baseType.types.map (.../node_modules/ts-json-schema-generator/dist/src/NodeParser/InterfaceNodeParser.js:33:72)
Triggered by the following typescript:
export type AnyJson = boolean | number | string | null | JsonArray | JsonMap;
export interface JsonMap { [key: string]: AnyJson; }
export interface JsonArray extends Array<AnyJson> {}
Removing JsonArray
from AnyJson union fixes the issue and allows the schema to generate.
from ts-json-schema-generator.
Another simple way to reproduce the error:
type Map<T> = { [ key: string]: T; };
export type Test = {
a: Map<Test>;
};
For some reason it works when inlining the Map type:
export type Test = {
a: { [ key: string]: Test; };
};
from ts-json-schema-generator.
I think I found the problem:
The class CircularReferenceNodeParser
is obviously responsible for solving circular reference problems but in this case it doesn't work. This parser creates an empty ReferenceType which is not yet connected to the real type and stores this type in a map called circular
. Other types which are created while creating the actual type will get this unfinished ReferenceType instead of producing an endless loop. This is fine but the problem is that for TypeReferenceNodes this unfinished ReferenceType is pushed into the arguments array on the context. And from these argument types the IDs are read when creating a key for the circular map. But this ID can not be read because the ReferenceType is not really referencing a type yet. And that's why it fails...
Or in other words this happens (with the example from my previous comment):
- Starting creation of type for TypeAliasDeclaration
export type Test = { a: Map<Test>; }
- This starts the creation of type for TypeLiteral
{ a: Map<Test>; }
- This starts the creation of type for TypeReference
Map<Test>
- This starts the creation of type for TypeReference
Test
- This again starts the creation of type for TypeAliasDeclaration
export type Test = { a: Map<Test>; }
which now returns the unfinished ReferenceType from step 1. - This unfinished reference type is pushed to the arguments array of the context.
- createType is called again, this time for the TypeAliasDeclaration
type Map<T> = { [ key: string]: T; }
- Key generation for this new ReferenceType now fails because this calls
getId()
on the unfinished ReferenceType from step 1 which doesn't have a referenced type yet.
Unfortunately I don't know yet how to solve this...
from ts-json-schema-generator.
Maybe it would be possible to separate the Type-ID creation from the actual Type creation so the ID is known to the ReferenceType before the actual type is created and therefor before the creation of other types are triggered by it?
To check if this would be possible I created an ugly workaround:
With this workaround the ReferenceType can now access the type ID via a WeakMap using the ts.Node
as key. I changed the InterfaceNodeParser
and the TypeAliasNodeParser
to put the generated ID into this map before creating the actual type, so with this workaround all the examples above are now working.
As already said, I only consider this an ugly workaround. There must be a cleaner way to solve this.
from ts-json-schema-generator.
Ah, forget the ugly workaround with the WeakMap. I guess it may not work always anyway because the ts.Node without the context is a bad WeakMap key.
But I think I found a better solution: I added an optional ReferenceType argument to to NodeParser::createType()
method. The CircularReferenceNodeParser passes the created ReferenceType via this argument to the actual node parser and each node parser can then decide if it wants to set the ID and name (Yes, that's also necessary, because ExposeNodeParser accesses it before type is finished) on the reference node before the actual type is created.
Still a little bit hacky but PR is incoming anyway.
from ts-json-schema-generator.
Related Issues (20)
- Error when following exports?
- Dist types now require @types/ts-expose-internals HOT 9
- Fix CJS imports HOT 8
- Invalid index in type HOT 11
- CLI - ENOENT: no such file or directory, open 'package.json' HOT 3
- Error: Unknown type "undefined" HOT 2
- Required types not allowed HOT 1
- Generator crashed when no package version is set HOT 4
- Any way to indicate that a string is actually a date-time? HOT 7
- Breaking changes from v1 to v2 HOT 1
- Support for `"format": "uri-reference"` HOT 3
- Incorrect typing when a type uses Omit and inherits properties from a grandparent interface
- `--expose all` breaks generation with generic types. HOT 4
- How do you use ajv with references? HOT 4
- create schema uses `anyOf` instead of `allOf` HOT 5
- When I use discriminator, I am getting an error where it can't find the specific field HOT 1
- Allow using dependencies schema on certain prop HOT 4
- Undefined reference in ObjectLiteralExpressionNodeParser when using typeof on a spread const HOT 2
- Schema generator fails when nested property name is StringLiteral (kind 11) HOT 4
- error generating schema for keyof typeof x HOT 4
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
D3
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
-
Recommend Topics
-
javascript
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
-
web
Some thing interesting about web. New door for the world.
-
server
A server is a program made to process requests and deliver data to clients.
-
Machine learning
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from ts-json-schema-generator.