Giter Club home page Giter Club logo

Comments (8)

domoritz avatar domoritz commented on August 18, 2024 1

I recommend https://astexplorer.net/ to look at what is actually defined.

from ts-json-schema-generator.

awinograd avatar awinograd commented on August 18, 2024 1

Here's a minimal repro in astexplorer.net for reference

https://astexplorer.net/#/gist/f418932fb2afef0eb5a16cd9fb2598f1/79e310c9b62ea6ef55e558242cb530c810743c68

from ts-json-schema-generator.

awinograd avatar awinograd commented on August 18, 2024

Thanks, that's a helpful resource!

from ts-json-schema-generator.

rfrey-rbx avatar rfrey-rbx commented on August 18, 2024

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.

kayahr avatar kayahr commented on August 18, 2024

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.

kayahr avatar kayahr commented on August 18, 2024

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):

  1. Starting creation of type for TypeAliasDeclaration export type Test = { a: Map<Test>; }
  2. This starts the creation of type for TypeLiteral { a: Map<Test>; }
  3. This starts the creation of type for TypeReference Map<Test>
  4. This starts the creation of type for TypeReference Test
  5. This again starts the creation of type for TypeAliasDeclaration export type Test = { a: Map<Test>; } which now returns the unfinished ReferenceType from step 1.
  6. This unfinished reference type is pushed to the arguments array of the context.
  7. createType is called again, this time for the TypeAliasDeclaration type Map<T> = { [ key: string]: T; }
  8. 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.

kayahr avatar kayahr commented on August 18, 2024

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:

https://github.com/vega/ts-json-schema-generator/compare/master...iplabs:workaround/circular-type-id?expand=1

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.

kayahr avatar kayahr commented on August 18, 2024

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)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo 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.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.