Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

circular constraint issue #13129

Closed
2 tasks done
mwenko opened this issue Mar 5, 2023 · 10 comments · Fixed by #13291
Closed
2 tasks done

circular constraint issue #13129

mwenko opened this issue Mar 5, 2023 · 10 comments · Fixed by #13291
Labels
typescript Types or Types-test related issue / Pull Request
Milestone

Comments

@mwenko
Copy link

mwenko commented Mar 5, 2023

Prerequisites

  • I have written a descriptive issue title
  • I have searched existing issues to ensure the bug has not already been reported

Mongoose version

7.0.0

Node.js version

16.14.2

MongoDB server version

4.4

Typescript version (if applicable)

4.9.5

Description

I get a compilation error when specifying the Schema inside a connection.model call.

Steps to Reproduce

I have the following line of code in a typescript project:

const allUserDocuments: UserDocument[] = await connection
        .model("Users", UserSchema)
        .find({})
        .exec();

When compiling the project, I get:

node_modules/typescript/lib/lib.es5.d.ts:1584:11 - error TS2313: Type parameter 'P' has a circular constraint.

1584     [P in K]: T[P];
               ~

  example.ts:60:52
         const allUserDocuments: UserDocument[] = await connection
                                                          ~~~~~~~~~~
             .model("Users", UserSchema)
       ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    Circularity originates in type at this location.

If I remove the UserSchema from the parameters like that:

    const allUserDocuments: UserDocument[] = await connection
        .model("Users")
        .find({})
        .exec();

it works.

doing skipLibCheck: true also resolves the problem, but that's not sth I wanna do.

Expected Behavior

This error should not happen.

@mwenko
Copy link
Author

mwenko commented Mar 5, 2023

I'm using NestJS with a mongoose package that probably needs to be updated: https://github.com/nestjs/mongoose

As this could be the issue I'm going to wait until a new version of it has been released and come back here if the issue hasn't been resolved.

@mwenko mwenko closed this as completed Mar 5, 2023
@vkarpov15
Copy link
Collaborator

Can you please provide a more complete code sample, like what your schema definitions look like?

@davidvorona
Copy link

Mongoose version: 7.0.2
Node version: 16.16.0
Typescript version: 4.9.5

I've also been getting this issue, and might be able to provide some more insight. An example of the offending code w/ schema definitions:

import { Schema, model, InferSchemaType } from "mongoose";

const DisbursementSchema = new Schema({
    paymentId: {
        type: String,
        required: true
    },
    paymentDate: {
        type: Date,
        required: true
    },
    buyer: {
        id: {
            type: Schema.Types.ObjectId,
            ref: "user"
        },
        username: {
            type: String
        },
        email: {
            type: String
        },
        city: {
            type: String
        },
        state: {
            type: String
        },
        deliveryZip: {
            type: String
        },
    },
    seller: {
        id: {
            type: Schema.Types.ObjectId,
            ref: "user"
        },
        username: {
            type: String
        },
        email: {
            type: String
        },
        createDate: {
            type: Date
        }
    },
    purchases: [
        ...
    ]
});

export type DisbursementModel = InferSchemaType<typeof DisbursementSchema>;

DisbursementSchema.index({ "paymentId": 1, "seller.id": 1 }, { unique: true });

export default model("disbursement", DisbursementSchema);

Compiling the project results in the following error, but only when used with the --build flag:

> tsc --build

node_modules/typescript/lib/lib.es5.d.ts:1584:11 - error TS2313: Type parameter 'P' has a circular constraint.

1584     [P in K]: T[P];
               ~

  src/models/accounting/Disbursement.ts:207:33
    207 export type DisbursementModel = InferSchemaType<typeof DisbursementSchema>;
                                        ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    Circularity originates in type at this location.


Found 1 error.

Avoiding the --build flag fixes the issue, though I was able to use the --build flag before I switched to automatic schema type inference. For those that do need the perks of typescript's build flag and don't want to maintain separate schema interfaces, I can see this being an issue.

@vkarpov15
Copy link
Collaborator

@davidvorona what is purchases in your schema? I don't see how the schema you pasted would cause a circular constraint, but I'll try it out.

@vkarpov15 vkarpov15 reopened this Mar 17, 2023
@vkarpov15 vkarpov15 added this to the 7.0.3 milestone Mar 17, 2023
@vkarpov15 vkarpov15 added has repro script There is a repro script, the Mongoose devs need to confirm that it reproduces the issue typescript Types or Types-test related issue / Pull Request labels Mar 17, 2023
@davidvorona
Copy link

This happened with very simple models as well, but here's the whole purchases array:

purchases: [
{
            ledgerId: {
                type: Schema.Types.ObjectId,
                ref: "ledger",
                required: true
            },
            item: {
                name: {
                    type: String
                },
                type: {
                    type: String,
                    enum: itemTypes
                }
            },
            purchasePrice: {
                type: Number
            },
            quantity: {
                type: Number
            },
            shipping: {
                cost: {
                    type: Number
                },
                // 0b01 isCombined, 0b10 isInternational, 0b11 isCombined/isInternational
                strategy: {
                    type: Number
                }
            },
            taxPrice: {
                type: Number
            },
            transactionFee: {
                percent: {
                    type: Number
                },
                discount: {
                    type: Number
                },
                total: {
                    type: Number
                }
            },
            processingFee: {
                percent: {
                    type: Number
                },
                fixed: {
                    type: Number
                },
                total: {
                    type: Number
                }
            },
            foreignTransactionFee: {
                percent: {
                    type: Number
                },
                total: {
                    type: Number
                }
            },
            groupModeratorFee: {
                percent: {
                    type: Number
                },
                total: {
                    type: Number
                }
            },
            paymentType: {
                type: String
            },
            purchaseDate: {
                type: Date
            },
            netPayment: {
                type: Number
            },
            disbursementInfo: {
                id: {
                    type: Schema.Types.ObjectId
                },
                isDisbursed: {
                    type: Boolean,
                    default: false,
                    required: true
                },
                date: {
                    type: Date
                },
                by: {
                    type: String
                },
                eWallet: {
                    entity: {
                        type: String
                    },
                    account: {
                        type: String
                    },
                    fullName: {
                        type: String
                    },
                    bankAccountNumber: {
                        type: Number
                    },
                    routingNumber: {
                        type: Number
                    }
                }
            },
            exceptionInfo: {
                id: {
                    type: Schema.Types.ObjectId
                },
                type: {
                    type: String,
                    enum: exceptionTypes
                },
                date: {
                    type: Date
                },
                by: {
                    type: String
                }
            }
        }
]

@vkarpov15
Copy link
Collaborator

I'm still unable to repro, below script compiles fine with --build.

import { Schema, model, InferSchemaType } from "mongoose";

const DisbursementSchema = new Schema({
    paymentId: {
        type: String,
        required: true
    },
    paymentDate: {
        type: Date,
        required: true
    },
    buyer: {
        id: {
            type: Schema.Types.ObjectId,
            ref: "user"
        },
        username: {
            type: String
        },
        email: {
            type: String
        },
        city: {
            type: String
        },
        state: {
            type: String
        },
        deliveryZip: {
            type: String
        },
    },
    seller: {
        id: {
            type: Schema.Types.ObjectId,
            ref: "user"
        },
        username: {
            type: String
        },
        email: {
            type: String
        },
        createDate: {
            type: Date
        }
    },
purchases: [
{
            ledgerId: {
                type: Schema.Types.ObjectId,
                ref: "ledger",
                required: true
            },
            item: {
                name: {
                    type: String
                },
                type: {
                    type: String,
                    //enum: itemTypes
                }
            },
            purchasePrice: {
                type: Number
            },
            quantity: {
                type: Number
            },
            shipping: {
                cost: {
                    type: Number
                },
                // 0b01 isCombined, 0b10 isInternational, 0b11 isCombined/isInternational
                strategy: {
                    type: Number
                }
            },
            taxPrice: {
                type: Number
            },
            transactionFee: {
                percent: {
                    type: Number
                },
                discount: {
                    type: Number
                },
                total: {
                    type: Number
                }
            },
            processingFee: {
                percent: {
                    type: Number
                },
                fixed: {
                    type: Number
                },
                total: {
                    type: Number
                }
            },
            foreignTransactionFee: {
                percent: {
                    type: Number
                },
                total: {
                    type: Number
                }
            },
            groupModeratorFee: {
                percent: {
                    type: Number
                },
                total: {
                    type: Number
                }
            },
            paymentType: {
                type: String
            },
            purchaseDate: {
                type: Date
            },
            netPayment: {
                type: Number
            },
            disbursementInfo: {
                id: {
                    type: Schema.Types.ObjectId
                },
                isDisbursed: {
                    type: Boolean,
                    default: false,
                    required: true
                },
                date: {
                    type: Date
                },
                by: {
                    type: String
                },
                eWallet: {
                    entity: {
                        type: String
                    },
                    account: {
                        type: String
                    },
                    fullName: {
                        type: String
                    },
                    bankAccountNumber: {
                        type: Number
                    },
                    routingNumber: {
                        type: Number
                    }
                }
            },
            exceptionInfo: {
                id: {
                    type: Schema.Types.ObjectId
                },
                type: {
                    type: String,
                    //enum: exceptionTypes
                },
                date: {
                    type: Date
                },
                by: {
                    type: String
                }
            }
        }
]
});

export type DisbursementModel = InferSchemaType<typeof DisbursementSchema>;

DisbursementSchema.index({ "paymentId": 1, "seller.id": 1 }, { unique: true });

export default model("disbursement", DisbursementSchema);

Given that compilation only fails with --build, it is likely due to your tsconfig.json. Can you please provide your tsconfig.json file?

For example, the tsconfig.json we're using is this one:

{
  "compilerOptions": {"strict": true},
  "include": ["./index.ts"]
}

@vkarpov15 vkarpov15 added can't reproduce Mongoose devs have been unable to reproduce this issue. Close after 14 days of inactivity. and removed has repro script There is a repro script, the Mongoose devs need to confirm that it reproduces the issue labels Mar 21, 2023
@vkarpov15 vkarpov15 removed this from the 7.0.3 milestone Mar 21, 2023
@mwenko
Copy link
Author

mwenko commented Mar 22, 2023

I'm still unable to repro, below script compiles fine with --build.

I found that setting esModuleInterop to false inside tsconfig.json works & the error disappeared.
So I assume this is the setting that causes conflicts.

{
        "module": "commonjs",
        "esModuleInterop": false,
        "removeComments": true,
        "emitDecoratorMetadata": true,
        "experimentalDecorators": true,
        "importHelpers": true,
        "allowSyntheticDefaultImports": true,
        "esModuleInterop": true,
        "target": "es2017",
        "lib": ["ES2019", "DOM"],
        "sourceMap": true,
        "outDir": "./dist",
        "baseUrl": "./",
        "incremental": true,
        "resolveJsonModule": true,
}

But what should I do if I wanna have it set to true?

@vkarpov15 vkarpov15 added has repro script There is a repro script, the Mongoose devs need to confirm that it reproduces the issue and removed can't reproduce Mongoose devs have been unable to reproduce this issue. Close after 14 days of inactivity. labels Mar 22, 2023
@vkarpov15 vkarpov15 added this to the 7.0.4 milestone Mar 22, 2023
@Jokero
Copy link
Contributor

Jokero commented Mar 25, 2023

@vkarpov15 I noticed same circular error in version 7. TL;DR: it's because of incremental=true in tsconfig.json

Simple example:

src/locality.ts:

import { InferSchemaType, Schema } from 'mongoose';

const schema = new Schema({});

export type LocalityRaw = InferSchemaType<typeof schema>;

Output:

> tsc

node_modules/typescript/lib/lib.es5.d.ts:1584:11 - error TS2313: Type parameter 'P' has a circular constraint.

1584     [P in K]: T[P];
               ~

  src/locality.ts:5:27
    5 export type LocalityRaw = InferSchemaType<typeof schema>;
                                ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    Circularity originates in type at this location.


Found 1 error in node_modules/typescript/lib/lib.es5.d.ts:1584

tsconfig.json:

{
    "compilerOptions": {
        "module": "commonjs",
        "target": "esnext",
        "outDir": "dist",
        "incremental": true
    },
    "include": [
        "src/**/*"
    ]
}

But if I change incremental to false or remove it at all, it starts working. In version 6.10.4 I didn't have such issue.

@vkarpov15 vkarpov15 modified the milestones: 7.0.4, 7.0.5 Apr 3, 2023
@joeskeen
Copy link

FWIW, I tried setting incremental=false in my tsconfig.json and it didn't make a difference. I did, however, revert back to 6.10.4 and it works fine now.

@vkarpov15 vkarpov15 removed the has repro script There is a repro script, the Mongoose devs need to confirm that it reproduces the issue label Apr 17, 2023
@vkarpov15
Copy link
Collaborator

@Jokero I've confirmed that I get the same error you see, I'm investigating to see if I can find a fix or workaround.

vkarpov15 added a commit that referenced this issue Apr 18, 2023
…remental by deferring `ResolveSchemaOptions<>`

Fix #13129
vkarpov15 added a commit that referenced this issue Apr 18, 2023
types(schema): avoid circular constraint in TSchemaOptions with --incremental by deferring `ResolveSchemaOptions<>`
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
typescript Types or Types-test related issue / Pull Request
Projects
None yet
5 participants