ts-json-schema-generator icon indicating copy to clipboard operation
ts-json-schema-generator copied to clipboard

Recursive types crashes

Open loucadufault opened this issue 1 year ago • 6 comments

Encountered with this repro:

npx ts-json-schema-generator --path 'schema.ts' --type 'Schema'

/workspaces/my-app/node_modules/ts-json-schema-generator/dist/ts-json-schema-generator.js:99
        throw error;
        ^

TypeError: Cannot read properties of undefined (reading 'getId')
    at /workspaces/my-app/node_modules/ts-json-schema-generator/dist/src/Utils/nodeKey.js:43:57
    at Array.map ()
    at getKey (/workspaces/my-app/node_modules/ts-json-schema-generator/dist/src/Utils/nodeKey.js:43:40)
    at Context.getCacheKey (/workspaces/my-app/node_modules/ts-json-schema-generator/dist/src/NodeParser.js:30:55)
    at ChainNodeParser.createType (/workspaces/my-app/node_modules/ts-json-schema-generator/dist/src/ChainNodeParser.js:25:41)
    at TypeReferenceNodeParser.createType (/workspaces/my-app/node_modules/ts-json-schema-generator/dist/src/NodeParser/TypeReferenceNodeParser.js:55:37)
    at ChainNodeParser.createType (/workspaces/my-app/node_modules/ts-json-schema-generator/dist/src/ChainNodeParser.js:28:54)
    at TypeReferenceNodeParser.createSubContext (/workspaces/my-app/node_modules/ts-json-schema-generator/dist/src/NodeParser/TypeReferenceNodeParser.js:62:62)
    at TypeReferenceNodeParser.createType (/workspaces/my-app/node_modules/ts-json-schema-generator/dist/src/NodeParser/TypeReferenceNodeParser.js:55:118)
    at ChainNodeParser.createType (/workspaces/my-app/node_modules/ts-json-schema-generator/dist/src/ChainNodeParser.js:28:54)

Node.js v20.9.0

schema.ts

import { Options } from 'sequelize'

export interface Schema {
  sequelize: Pick<Options, 'host'>
}   

package.json

"sequelize": "^6.35.2"

Investigating, the culprit seems to be this path in Options interface from sequelize:

Options['define']['defaultScope']['where']

Which is the recursive AllowNotOrAndWithImplicitAndArrayRecursive type, see https://github.com/sequelize/sequelize/blob/b8212434b89e1622f86d1f8e1ea1a5daa060cea5/packages/core/src/dialects/abstract/where-sql-builder-types.ts#L17.

loucadufault avatar Feb 01 '24 22:02 loucadufault

Also ran tsc, which is working with no errors.

loucadufault avatar Feb 01 '24 22:02 loucadufault

Thanks for the report. Can you provide a minimal reproducible example that demonstrates the issue?

domoritz avatar Feb 01 '24 22:02 domoritz

@domoritz Anything specifically missing from the reproducible example provided in the ticket?

loucadufault avatar Feb 02 '24 13:02 loucadufault

It's not minimal. The smaller, the easier it will be to identify whether this is a knows issue or a new issue and how to fix it.

domoritz avatar Feb 02 '24 16:02 domoritz

Considering it is a total of 4 LoC, how do you propose I minimize this further?

loucadufault avatar Feb 02 '24 18:02 loucadufault

It's referring to some extra code. I tried to extract the code for AllowNotOrAndWithImplicitAndArrayRecursive and it seems to work.

type AllowArray<T> = T | T[];

interface OpTypes {
    readonly and: unique symbol;
    readonly or: unique symbol;
    readonly not: unique symbol;
}

const Op: OpTypes = {
    and: Symbol.for("and"),
    or: Symbol.for("or"),
    not: Symbol.for("not"),
} as OpTypes;

type AllowNotOrAndWithImplicitAndArrayRecursive<T> = AllowArray<
    | T
    | { [Op.or]: AllowArray<AllowNotOrAndWithImplicitAndArrayRecursive<T>> }
    | { [Op.and]: AllowArray<AllowNotOrAndWithImplicitAndArrayRecursive<T>> }
    | { [Op.not]: AllowNotOrAndWithImplicitAndArrayRecursive<T> }
>;

export type Test = AllowNotOrAndWithImplicitAndArrayRecursive<number>;

I ran yarn --silent run run --path 'test.ts' --type 'Test'

domoritz avatar Feb 02 '24 18:02 domoritz