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

Type instantiation is excessively deep and possibly infinite.ts(2589) #12277

Closed
1 task done
hmz22 opened this issue Aug 14, 2022 · 18 comments · Fixed by #12479
Closed
1 task done

Type instantiation is excessively deep and possibly infinite.ts(2589) #12277

hmz22 opened this issue Aug 14, 2022 · 18 comments · Fixed by #12479
Labels
typescript Types or Types-test related issue / Pull Request
Milestone

Comments

@hmz22
Copy link

hmz22 commented Aug 14, 2022

Prerequisites

  • I have written a descriptive issue title

Mongoose version

6.5.2

Node.js version

14.18.3

MongoDB version

4.4

Operating system

No response

Operating system version (i.e. 20.04, 11.3, 10)

No response

Issue

when use bulkwrite show ts error can help for solved this error

this my model:

export class BaseModel {
  @Field()
  _id?: string;

  @Field()
  createdAt?: Date;

  @Field()
  updatedAt?: Date
}
export class Member extends BasicModel {
  @Field(() => GraphQLBigInt)
  @prop()
  memberId?: number;

  @Field({ nullable: true })
  @prop()
  firstname?: string;

  @Field()
  @prop()
  lastname?: string;

  @prop()
  password?: string;

  @prop()
  public regMember?: RegMember;
}

@ObjectType()
export class MemberData {
  @Field(() => [Member])
  docs?: Member[];
}

export const MemberModel = getModelForClass(Member) as ISoftDeleteModel<
  Member,
  typeof Member
>;

sample code:

MemberModel.bulkWrite([
     {
       updateOne: {
         filter: {
           firstname: "test"
         },
         update: {
           firstname:"guide"
         }
       }
     }
   ])

in this block show error:

...
filter: {
            firstname: "test"
          },
...

and show this error:

(property) firstname: string
Type instantiation is excessively deep and possibly infinite.ts(2589)
Type of property 'Duplex' circularly references itself in mapped type '{ [Key in "prototype" | "on" | "once" | "setMaxListeners" | "listenerCount" | "pipeline" | "getEventListeners" | "errorMonitor" | "captureRejectionSymbol" | "captureRejections" | "defaultMaxListeners" | ... 14 more ... | "consumers"]: (typeof Writable)[Key] extends typeof Writable ? [...] : typeof Writable extends (...'.ts(2615)
Type of property 'PassThrough' circularly references itself in mapped type '{ [Key in "prototype" | "on" | "once" | "setMaxListeners" | "listenerCount" | "pipeline" | "getEventListeners" | "errorMonitor" | "captureRejectionSymbol" | "captureRejections" | "defaultMaxListeners" | ... 14 more ... | "consumers"]: (typeof Writable)[Key] extends typeof Writable ? [...] : typeof Writable extends (...'.ts(2615)
Type of property 'Query' circularly references itself in mapped type '{ get: ["get"]; set: ["set"]; default: ["default"]; deleteModel: ["deleteModel"]; models: any; model: ["model"]; modelNames: ["modelNames"]; plugin: ["plugin"]; startSession: ["startSession"]; ... 35 more ...; mquery: [...] | [...]; }'.ts(2615)
Type of property 'Readable' circularly references itself in mapped type '{ [Key in "prototype" | "on" | "once" | "setMaxListeners" | "listenerCount" | "pipeline" | "getEventListeners" | "errorMonitor" | "captureRejectionSymbol" | "captureRejections" | "defaultMaxListeners" | ... 14 more ... | "consumers"]: (typeof Writable)[Key] extends typeof Writable ? [...] : typeof Writable extends (...'.ts(2615)
Type of property 'Stream' circularly references itself in mapped type '{ [Key in "prototype" | "on" | "once" | "setMaxListeners" | "listenerCount" | "pipeline" | "getEventListeners" | "errorMonitor" | "captureRejectionSymbol" | "captureRejections" | "defaultMaxListeners" | ... 14 more ... | "consumers"]: (typeof Writable)[Key] extends typeof Writable ? [...] : typeof Writable extends (...'.ts(2615)
Type of property 'Transform' circularly references itself in mapped type '{ [Key in "prototype" | "on" | "once" | "setMaxListeners" | "listenerCount" | "pipeline" | "getEventListeners" | "errorMonitor" | "captureRejectionSymbol" | "captureRejections" | "defaultMaxListeners" | ... 14 more ... | "consumers"]: (typeof Writable)[Key] extends typeof Writable ? [...] : typeof Writable extends (...'.ts(2615)
Type of property 'Writable' circularly references itself in mapped type '{ from: ["from"]; prototype: ["prototype"] | ["prototype", "read"] | ["prototype", "destroy"] | ["prototype", "eventNames"] | ["prototype", "addListener"] | ["prototype", "on"] | ... 38 more ... | [...]; ... 25 more ...; consumers: [...] | ... 4 more ... | [...]; }'.ts(2615)
Type of property 'Writable' circularly references itself in mapped type '{ from: ["from"]; prototype: ["prototype"] | ["prototype", "read"] | ["prototype", "destroy"] | ["prototype", "eventNames"] | ["prototype", "addListener"] | ["prototype", "on"] | ... 55 more ... | [...]; ... 25 more ...; consumers: [...] | ... 4 more ... | [...]; }'.ts(2615)
Type of property 'Writable' circularly references itself in mapped type '{ from: ["from"]; prototype: ["prototype"] | ["prototype", "read"] | ["prototype", "destroy"] | ["prototype", "eventNames"] | ["prototype", "addListener"] | ["prototype", "on"] | ... 57 more ... | [...]; ... 25 more ...; consumers: [...] | ... 4 more ... | [...]; }'.ts(2615)
Type of property 'Writable' circularly references itself in mapped type '{ prototype: ["prototype"] | ["prototype", "eventNames"] | ["prototype", "addListener"] | ["prototype", "on"] | ["prototype", "once"] | ["prototype", "removeListener"] | ... 10 more ... | [...]; ... 22 more ...; consumers: [...] | ... 4 more ... | [...]; }'.ts(2615)
Type of property '_mongooseOptions' circularly references itself in mapped type '{ remove: ["remove"]; populate: ["populate"]; lean: ["lean"]; catch: ["catch"]; then: ["then"]; tailable: ["tailable"]; error: ["error"]; slice: ["slice"]; $where: ["$where"]; deleteOne: ["deleteOne"]; ... 85 more ...; within: [...]; }'.ts(2615)
Type of property 'autoEncryption' circularly references itself in mapped type '{ raw: ["raw"]; forceServerObjectId: ["forceServerObjectId"]; readConcern: ["readConcern"] | ["readConcern", "toJSON"] | ["readConcern", "level"]; retryWrites: ["retryWrites"]; ... 65 more ...; tls: [...]; }'.ts(2615)
Type of property 'base' circularly references itself in mapped type '{ [Key in keyof Model<any, {}, {}, {}, any>]: Model<any, {}, {}, {}, any>[Key] extends Model<any, {}, {}, {}, any> ? [Key] : Model<any, {}, {}, {}, any> extends Model<...>[Key] ? [...] : Model<...>[Key] extends readonly (infer ArrayType)[] ? Model<...> extends ArrayType ? [...] : ArrayType extends Model<...> ? [...]...'.ts(2615)
Type of property 'childSchemas' circularly references itself in mapped type '{ [Key in keyof Schema<any, Model<any, any, any, any, any>, {}, {}, {}, {}, "type", { [x: string]: any; }>]: Schema<any, Model<any, any, any, any, any>, {}, {}, {}, {}, "type", { ...; }>[Key] extends Schema<...> ? [...] : Schema<...> extends Schema<...>[Key] ? [...] : Schema<...>[Key] extends readonly (infer ArrayTy...'.ts(2615)
Type of property 'collections' circularly references itself in mapped type '{ close: ["close"]; collection: ["collection"]; db: ["db"] | ["db", "collection"] | ["db", "options"] | ["db", "readConcern"] | ["db", "readConcern", "toJSON"] | ["db", "readConcern", "level"] | ... 103 more ... | [...]; ... 44 more ...; eventNames: [...]; }'.ts(2615)
Type of property 'conn' circularly references itself in mapped type '{ [Key in keyof Collection<Document>]: Collection<Document>[Key] extends Collection<Document> ? [Key] : Collection<...> extends Collection<...>[Key] ? [...] : Collection<...>[Key] extends readonly (infer ArrayType)[] ? Collection<...> extends ArrayType ? [...] : ArrayType extends Collection<...> ? [...] : [...] : [....'.ts(2615)
Type of property 'db' circularly references itself in mapped type '{ validate: ["validate"]; remove: ["remove"]; populate: ["populate"]; $where: ["$where"]; baseModelName: ["baseModelName"]; collection: ["collection"] | ["collection", ...any[]]; db: ["db"] | [...]; ... 61 more ...; ensureIndexes: [...]; }'.ts(2615)
Type of property 'defaultTransactionOptions' circularly references itself in mapped type '{ [Key in keyof ClientSession]: ClientSession[Key] extends ClientSession ? [Key] : ClientSession extends ClientSession[Key] ? [...] : ClientSession[Key] extends readonly (infer ArrayType)[] ? ClientSession extends ArrayType ? [...] : ArrayType extends ClientSession ? [...] : [...] : [...] | [...]; }'.ts(2615)
Type of property 'discriminators' circularly references itself in mapped type '{ [Key in keyof Model<any, {}, {}, {}, any>]: Model<any, {}, {}, {}, any>[Key] extends Model<any, {}, {}, {}, any> ? [Key] : Model<any, {}, {}, {}, any> extends Model<...>[Key] ? [...] : Model<...>[Key] extends readonly (infer ArrayType)[] ? Model<...> extends ArrayType ? [...] : ArrayType extends Model<...> ? [...]...'.ts(2615)
Type of property 'discriminators' circularly references itself in mapped type '{ [Key in keyof Schema<any, Model<any, any, any, any, any>, {}, {}, {}, {}, "type", { [x: string]: any; }>]: Schema<any, Model<any, any, any, any, any>, {}, {}, {}, {}, "type", { ...; }>[Key] extends Schema<...> ? [...] : Schema<...> extends Schema<...>[Key] ? [...] : Schema<...>[Key] extends readonly (infer ArrayTy...'.ts(2615)
Type of property 'keyVaultClient' circularly references itself in mapped type '{ [Key in keyof AutoEncryptionOptions]: AutoEncryptionOptions[Key] extends AutoEncryptionOptions ? [...] : AutoEncryptionOptions extends AutoEncryptionOptions[Key] ? [...] : AutoEncryptionOptions[Key] extends readonly (infer ArrayType)[] ? AutoEncryptionOptions extends ArrayType ? [...] : ArrayType extends AutoEncry...'.ts(2615)
Type of property 'model' circularly references itself in mapped type '{ options: ["options"] | ["options", string]; populate: ["populate"]; match: ["match"]; select: ["select"]; transform: ["transform"]; model: ["model"] | ["model", ...any[]]; path: ["path"]; perDocumentLimit: [...]; strictPopulate: [...]; justOne: [...]; }'.ts(2615)
Type of property 'models' circularly references itself in mapped type '{ [Key in keyof Connection]: Connection[Key] extends Connection ? [Key] : Connection extends Connection[Key] ? [...] : Connection[Key] extends readonly (infer ArrayType)[] ? Connection extends ArrayType ? [...] : ArrayType extends Connection ? [...] : [...] : [...] | [...]; }'.ts(2615)
Type of property 'models' circularly references itself in mapped type '{ get: ["get"]; set: ["set"]; default: ["default"]; deleteModel: ["deleteModel"]; models: ["models"] | ["models", string] | ["models", string, ...any[]]; model: ["model"]; modelNames: ["modelNames"]; ... 37 more ...; mquery: [...] | [...]; }'.ts(2615)
Type of property 'options' circularly references itself in mapped type '{ options: ["options"] | ["options", ...any[]]; close: ["close"]; db: ["db"]; readConcern: ["readConcern"] | ["readConcern", "toJSON"] | ["readConcern", "level"]; readPreference: [...] | ... 12 more ... | [...]; ... 24 more ...; withSession: [...]; }'.ts(2615)
Type of property 'options' circularly references itself in mapped type '{ options: ["options"] | ["options", ...any[]]; isPinned: ["isPinned"]; recoveryToken: ["recoveryToken"]; isStarting: ["isStarting"]; isActive: ["isActive"]; isCommitted: ["isCommitted"]; }'.ts(2615)
Type of property 'paths' circularly references itself in mapped type '{ [Key in keyof Schema<any, Model<any, any, any, any, any>, {}, {}, {}, {}, "type", { [x: string]: any; }>]: Schema<any, Model<any, any, any, any, any>, {}, {}, {}, {}, "type", { ...; }>[Key] extends Schema<...> ? [...] : Schema<...> extends Schema<...>[Key] ? [...] : Schema<...>[Key] extends readonly (infer ArrayTy...'.ts(2615)
Type of property 'populate' circularly references itself in mapped type '{ populate: ["populate"] | ["populate", ...any[]]; lean: ["lean"]; strict: ["strict"]; sanitizeProjection: ["sanitizeProjection"]; sanitizeFilter: ["sanitizeFilter"]; }'.ts(2615)
Type of property 'prototype' circularly references itself in mapped type '{ prototype: ["prototype"] | ["prototype", ...any[]]; }'.ts(2615)
Type of property 'schema' circularly references itself in mapped type '{ options: ["options"]; validate: ["validate"]; get: ["get"]; schema: ["schema"] | ["schema", ...any[]]; set: ["set"]; index: ["index"]; default: ["default"]; text: ["text"]; cast: ["cast"]; required: [...]; ... 10 more ...; validators: [...] | ... 11 more ... | [...]; }'.ts(2615)
Type of property 'schema' circularly references itself in mapped type '{ schema: ["schema"] | ["schema", ...any[]]; model: ["model"]; }'.ts(2615)
Type of property 'session' circularly references itself in mapped type '{ [Key in keyof TransactionOptions]: TransactionOptions[Key] extends TransactionOptions ? [Key] : TransactionOptions extends TransactionOptions[Key] ? [...] : TransactionOptions[Key] extends readonly (infer ArrayType)[] ? TransactionOptions extends ArrayType ? [...] : ArrayType extends TransactionOptions ? [...] : [...'.ts(2615)
Type of property 'transaction' circularly references itself in mapped type '{ [Key in keyof ClientSession]: ClientSession[Key] extends ClientSession ? [Key] : ClientSession extends ClientSession[Key] ? [...] : ClientSession[Key] extends readonly (infer ArrayType)[] ? ClientSession extends ArrayType ? [...] : ArrayType extends ClientSession ? [...] : [...] : [...] | [...]; }'.ts(2615)
@hmz22 hmz22 added help This issue can likely be resolved in GitHub issues. No bug fixes, features, or docs necessary help wanted labels Aug 14, 2022
@AbdelrahmanHafez
Copy link
Collaborator

Welcome @hmz22

You seem to be using typegoose, can you provide an example using only mongoose that reproduces the issue?
If not, I'd say the place for that issue would be typegoose, or perhaps the maintainer of typegoose, @hasezoey, might be able to offer some help here.

@AbdelrahmanHafez AbdelrahmanHafez added the typescript Types or Types-test related issue / Pull Request label Aug 15, 2022
@hasezoey
Copy link
Collaborator

Original Issue in typegoose (because author does not seem to have linked it): typegoose/typegoose#752

this issue seems to be about bulkWrite() -> updateOne -> filter giving some kind of typescript error, though i dont know why

@hasezoey
Copy link
Collaborator

i have locally tried the issue, and could reproduce it in typegoose and plain mongoose

// NodeJS: 18.7.0
// MongoDB: 5.0 (Docker)
// Typescript 4.7.4
import * as mongoose from 'mongoose'; // mongoose@6.5.2

type DocumentType<T> = mongoose.Document<any, any, T> & T;

interface BaseModelClassDoc {
  firstname: string;
}

const baseModelClassSchema = new mongoose.Schema({
  firstname: String,
});

const BaseModel = mongoose.model<mongoose.Model<DocumentType<BaseModelClassDoc>>>('test', baseModelClassSchema);

(async () => {
  await mongoose.connect(`mongodb://localhost:27017/`, {
    dbName: 'verifyMASTER',
  });

  await BaseModel.bulkWrite([
    {
      updateOne: {
        update: {
          firstname: 'test', // Type instantiation is excessively deep and possibly infinite.ts(2589)
        },
        filter: {
          firstname: 'asdsd',
        },
      },
    },
  ]);

  await mongoose.disconnect();
})();

Reproduction Repository / branch: https://github.com/typegoose/typegoose-testing/tree/verify752
Where the latest commit is the mongoose code and the previous is the typegoose code

@AbdelrahmanHafez AbdelrahmanHafez added has repro script There is a repro script, the Mongoose devs need to confirm that it reproduces the issue and removed help This issue can likely be resolved in GitHub issues. No bug fixes, features, or docs necessary help wanted labels Aug 22, 2022
@IslandRhythms IslandRhythms removed the has repro script There is a repro script, the Mongoose devs need to confirm that it reproduces the issue label Aug 24, 2022
@IslandRhythms
Copy link
Collaborator

This issue does not happen on 6.5.1

@SK-FComputer
Copy link

@IslandRhythms @hasezoey I seem to have the same problem with mongoose=6.5.3, typescript=4.8.2 and typegoose=9.11.2
Only is a problem after upgrading from mongoose=6.5.0

@SK-FComputer
Copy link

@AbdelrahmanHafez tagging you as well as i missed that you're a collaborator

@hasezoey
Copy link
Collaborator

This issue does not happen on 6.5.1

@IslandRhythms why was the "has repro script" label removed when it stated mongoose version 6.5.2?

i have also tested now 6.5.3 and can reproduce the error (with the same code), i have also tried typescript 4.8.2 (both changes can be found in the linked repository+branch)

@IslandRhythms
Copy link
Collaborator

@hasezoey we use the typescript label to indicate there is a bug with typescript and mongoose, as opposed to confirmed bug which indicates a problem with mongoose. has repro script was removed because I could reproduce it on 6.5.2 and wanted to leave a note stating that on 6.5.1 the issue was not present so val could look back to there for ease of debugging.

@hasezoey
Copy link
Collaborator

we use the typescript label to indicate there is a bug with typescript and mongoose, as opposed to confirmed bug which indicates a problem with mongoose

thats what i assumed

as repro script was removed because I could reproduce it on 6.5.2 and wanted to leave a note stating that on 6.5.1 the issue was not present so val could look back to there for ease of debugging.

isnt that the purpose of having has repro script(on latest version) instead of nothing or needs repro script?
or do you mean * repro script labels are only for runtime things but not for typescript / types things?

@IslandRhythms
Copy link
Collaborator

has repro script means that the issue has a repro script, but needs to be ran in order to determine if there is a bug or not. Once a bug is detected from running the script, it no longer needs the has repro script because a determination has been made on the issue. When a maintainer comes to look at the issue that has label confirmed bug or typescript etc they are expecting a script that reproduces or does not reproduce the issue in question to be present so they can confirm it themselves.

@IslandRhythms
Copy link
Collaborator

IslandRhythms commented Aug 29, 2022

needs repro script is just when an issue is created with no repro script and there might be enough information that a maintainer could reproduce the issue themself. However, it would be preferred that the issue reported does so for quickness and accuracy because in the attempt to reproduce the error something could be missed that is needed in the script to reproduce the bug and the issue reporter would know what that is.

@hasezoey
Copy link
Collaborator

thanks for the explanation @IslandRhythms, it seems we had a different understanding of the label meanings, thanks for clarifying (personally in my projects i have needs repro script if there is no repro script present and has repro script if a repro script is present and actually reproduces it, regardless if other labels are present)

@SK-FComputer
Copy link

Still an issue with Typescript=4.8.3, which seemed to have fixes for type narrowing..

@SK-FComputer
Copy link

@hasezoey
Copy link
Collaborator

@SK-FComputer with what mongoose version were you testing?

@SK-FComputer
Copy link

With 6.6.0 and 6.5.5 if i remember correctly

@dimfeld
Copy link

dimfeld commented Sep 16, 2022

If it helps, here's a minimal repro in the Typescript playground. No way to pin the versions there that I can see but presumably it's using the latest version of each package. I'm also seeing in my actual work with mongoose 6.6.1 and mongodb 4.9.1.

https://www.typescriptlang.org/play?#code/JYWwDg9gTgLgBAbzgQQHYE8BCBXANgawHUpgYBTAeTDKgEMZgJUAaOCgIwCsyBjGASQAmcAL5wAZlAgg4AchBMA5hEHtZAbgBQoSLERwAIhB7YQZVPDGTpchamUQAzmQ2bNPJo-jYwg+mTgALhQMHAJiUkpqOgYmAB4jEzMLAD44AF44TQRNODy4Hz9yClQyYJz8yolgXHIocrgAfWBBYNKAdzYuXgFBAAoASlFmXKq8wv9y0bHKgBJnGCmZ5bgAIlp2HlXg1cEycVXplZEjypOzzREtTSA

import { AnyBulkWriteOperation, ObjectId } from 'mongodb';
import { Document } from 'mongoose';

const update : AnyBulkWriteOperation<Document> = 
{
    updateOne: {
        filter: { _id: new ObjectId() },
        update: {
            $set: {
                "abc": "def"
            }
        }
    }
};

@vkarpov15 vkarpov15 added this to the 6.6.3 milestone Sep 26, 2022
@vkarpov15
Copy link
Collaborator

Based off of @hasezoey 's script here: #12277 (comment) I'd advise either using Mongoose's automatic type inference:

const BaseModel = mongoose.model<typeof baseModelClassSchema>('test', baseModelClassSchema);

or calling mongoose.model<> with the raw doc type as the first generic:

const BaseModel = mongoose.model<BaseModelClassDoc>('test', baseModelClassSchema);

rather than trying to manually create a hydrated document type and passing it to mongoose.model<>. That being said, we'll investigate more to see if we can come up with a fix.

@vkarpov15 vkarpov15 added this to the 6.6.4 milestone Sep 30, 2022
vkarpov15 added a commit that referenced this issue Oct 3, 2022
fix(types): avoid "excessively deep" type instantiation error when using bulkWrite() with type that extends from document
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
7 participants