vega / ts-json-schema-generator

Generate JSON schema from your Typescript sources
MIT License
1.43k stars 190 forks source link

Error: Reference type not set yet #192

Open domoritz opened 5 years ago

domoritz commented 5 years ago

In https://github.com/vega/vega-lite/pull/5290 and https://travis-ci.org/vega/vega-lite/jobs/571493756.

domoritz commented 5 years ago

We can reproduce this with keyof HTMLBodyElementEventMap and also Window. It looks like the Window type has some complications we don't deal with well.

Two solutions are: 1) support Window 2) ignore the values if we do keyof.

dartess commented 4 years ago

Omit + recursion give the same error:

export interface Comment {
    text: string;
    reply: Omit<Comment, 'reply'>;
}
zsalzbank commented 4 years ago

I'm getting something similar with this example:

export interface X {
  x: string;
}

export interface Y {
  y: string;
}

export type Inner<T> = {
  inner: Wrapper<T>[];
};

export type Wrapper<T> = T & Inner<Y>;

export type Output = Wrapper<X>;
zsalzbank commented 4 years ago

I'd love to fix this if somebody could point me in the right direction.

domoritz commented 4 years ago

The issue is somewhere in the cycle tracking, I think. The best way to debug this is to setup the repo, create a small example, and then step through the code with a debugger (follow package.json debug).

domoritz commented 4 years ago

From @Cyrus-d

in my repository, I have implemented the FunctionTypeFormatter to fulfil my needs. so to reproduce the problem In your repository I have changed the test as follow:

export type MyType = MyElement;

type MyFunction = MyElement | null;

interface MyElement<T extends string | MyFunction = string | MyFunction> {
    type: T;
}

this will throw Reference type ID not set yet error.

I think the problem is related to UnionType that trying to access ReferenceType to early for this line:

type MyFunction = MyElement | null;

For now, to solve it I have added the following line of the code to the CircularReferenceNodeParser file.

it will work however it will use ids for the interface names:

interface-572149719-68-159-572149719-0-160

I can overcome this by setting expose: "all", not sure if its normal behaviour?

here is the repository:

https://github.com/Cyrus-d/ts-to-json/tree/original

Test result with expose: "all":

{
    "$schema": "http://json-schema.org/draft-07/schema#",
    "$ref": "#/definitions/MyType",
    "definitions": {
        "MyType": {
            "$ref": "#/definitions/MyElement"
        },
        "MyElement": {
            "type": "object",
            "properties": {
                "type": {
                    "anyOf": [
                        {
                            "type": "string"
                        },
                        {
                            "$ref": "#/definitions/MyFunction"
                        }
                    ]
                }
            },
            "required": [
                "type"
            ],
            "additionalProperties": false
        },
        "MyFunction": {
            "anyOf": [
                {
                    "$ref": "#/definitions/MyElement"
                },
                {
                    "type": "null"
                }
            ]
        }
    }
}

Test result with expose: "export":

{
    "$schema": "http://json-schema.org/draft-07/schema#",
    "$ref": "#/definitions/MyType",
    "definitions": {
        "MyType": {
            "type": "object",
            "properties": {
                "type": {
                    "anyOf": [
                        {
                            "type": "string"
                        },
                        {
                            "anyOf": [
                                {
                                    "$ref": "#/definitions/interface-572149719-68-159-572149719-0-160"
                                },
                                {
                                    "type": "null"
                                }
                            ]
                        }
                    ]
                }
            },
            "required": [
                "type"
            ],
            "additionalProperties": false
        },
        "interface-572149719-68-159-572149719-0-160": {
            "type": "object",
            "properties": {
                "type": {
                    "anyOf": [
                        {
                            "type": "string"
                        },
                        {
                            "anyOf": [
                                {
                                    "$ref": "#/definitions/interface-572149719-68-159-572149719-0-160"
                                },
                                {
                                    "type": "null"
                                }
                            ]
                        }
                    ]
                }
            },
            "required": [
                "type"
            ],
            "additionalProperties": false
        }
    }
}
orgads commented 4 years ago

Hi,

Here's an example that reproduces the issue for me: test.ts

import { Test2 } from './test2';

export interface Test {
  test2: Test2;
}

test2.ts

import { Test } from './test';

export interface Test2 {
  test?: Partial<Test>;
}

Run:

ts-json-schema-generator --path test.ts --tsconfig tsconfig.json --type Test --out test.json
randygylling commented 4 years ago

Has anyone discovered a work around for this?

darkowic commented 3 years ago

I have created a repository with different schema generators to compare its capability: https://github.com/Guidewire/ts-to-json-schema-tests. By introducing the custom formatters feature here (it's exactly what we need!), I was able to parse simple type with a callback. This problem still occurs for more advanced types. I've fixed recursive problems in typescript-json-schema in this PR so, it may be useful to fix this.

I didn't have time to dive into this codebase and actually this one is a bit harder to understand (much more abstraction), but the custom formatters functionality is something we need so maybe we will do something with this soon :P

broofa commented 2 years ago

[Edited to provide better test case examples]

Is there a status update on this?

I'm currently running into this issue (circular type references) in the following cases (in case more test cases are needed):

(Note: I'm using custom generator to handle unknown function types.)

broofa commented 2 years ago

Breadcrumb for others: I ended up switching to typescript-json-schema. It handles this issue, as well as a number of other issues I was running into (such as module resolution in the context of yarn workspaces.)

andreicioromila commented 1 year ago

This is still reproducing in "ts-json-schema-generator": "1.1.2"

bdarcus commented 1 year ago

The schema generator landscape is in a bit of a weird spot ATM.

I tried to switch to this project, as the other is in maintenance mode and recommends this, but schema conversion fails with this error, which is still open after almost four years.

❯ ts-json-schema-generator --no-type-check --path ./npm/src/style.ts --type Style --tsconfig ./tsconfig.json
/usr/local/lib/node_modules/ts-json-schema-generator/dist/ts-json-schema-generator.js:95
        throw error;
        ^

Error: Reference type not set yet
    at ReferenceType.getType (/usr/local/lib/node_modules/ts-json-schema-generator/dist/src/Type/ReferenceType.js:32:19)
    at derefType (/usr/local/lib/node_modules/ts-json-schema-generator/dist/src/Utils/derefType.js:13:31)
    at derefAndFlattenUnions (/usr/local/lib/node_modules/ts-json-schema-generator/dist/src/NodeParser/IntersectionNodeParser.js:33:47)
    at /usr/local/lib/node_modules/ts-json-schema-generator/dist/src/NodeParser/IntersectionNodeParser.js:36:28
    at Array.reduce (<anonymous>)
    at derefAndFlattenUnions (/usr/local/lib/node_modules/ts-json-schema-generator/dist/src/NodeParser/IntersectionNodeParser.js:35:30)
    at Array.map (<anonymous>)
    at translate (/usr/local/lib/node_modules/ts-json-schema-generator/dist/src/NodeParser/IntersectionNodeParser.js:46:26)
    at IntersectionNodeParser.createType (/usr/local/lib/node_modules/ts-json-schema-generator/dist/src/NodeParser/IntersectionNodeParser.js:28:16)
    at ChainNodeParser.createType (/usr/local/lib/node_modules/ts-json-schema-generator/dist/src/ChainNodeParser.js:28:54)

Node.js v20.2.0
themetalfleece commented 6 months ago

I was getting this error due to the following:

type A = {
  x: number;
  o: {
    type: 'foo' | 'bar';
    otherType?: A['o']['type'] | null;
  }
}

The issue was with the self-reference, so I had to do the following workaround:

type FooBar = 'foo' | 'bar';

type A = {
  x: number;
  o: {
    type: FooBar;
    otherType?: FooBar | null;
  }
}