question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

Typescript: Type instantiation is excessively deep and possibly infinite

See original GitHub issue

Do you want to request a feature or report a bug?

Bug

What is the current behavior?

After upgrading to use the new builtin types (previously using Mongoose version 5.10.9 and @types/mongoose": "^5.10.3) I am getting the error “Type instantiation is excessively deep and possibly infinite” on the following type of code:

return await Notification.find({ user: user._id }, 'message createdAt link').exec();

The User schema is quite large, but it’s never been an issue before for me to find based on the recorded ObjectId this way.

If the current behavior is a bug, please provide the steps to reproduce.

Where the schema is like this:

import mongoose from 'mongoose';
import { IUser } from './user';

const NotificationSchema = new mongoose.Schema(
  {
    user: {
      type: mongoose.Schema.Types.ObjectId,
      ref: 'User',
      required: true,
    },
    message: { type: String, required: true },
    link: { type: String, required: true },
  },
  {
    timestamps: true,
  },
);

export interface INotification extends mongoose.Document, mongoose.SchemaTimestampsConfig {
  user: IUser;
  message: string;
}

const Notification = mongoose.model<INotification>('Notification', NotificationSchema);
export default Notification;

tsconfig.json:

{
  "compilerOptions": {
    "target": "es2019",
    "module": "commonjs",
    "outDir": "dist",
    "strict": true,
    "alwaysStrict": true,
    "typeRoots": [
      "typings",
      "./node_modules/@types"
    ],
    "allowSyntheticDefaultImports": true,
    "esModuleInterop": true,
    "resolveJsonModule": true,
    "forceConsistentCasingInFileNames": true,
    "removeComments": true,
  },
	"include": [
    "src/**/*",
    "typings"
	],
}

What is the expected behavior?

No Typescript error

What are the versions of Node.js, Mongoose and MongoDB you are using? Note that “latest” is not a version.

Versions: Node: v14.16.0 Mongoose: 5.12.6 MongoDB: 4.2.3 Typescript: 4.2.4

Issue Analytics

  • State:closed
  • Created 2 years ago
  • Comments:8

github_iconTop GitHub Comments

1reaction
vkarpov15commented, May 16, 2021

Thanks for the repro script, we’ve confirmed that this is an issue and we found a couple of workarounds. The funny thing is that, if you remove ‘fourth’, everything works fine, so it isn’t an infinite type recursion, just that we’re hitting an arbitrary limit in TypeScript.

Specifically, this error is caused by Mongoose’s UpdateQuery type and its use of @types/mongodb’s OnlyFieldsOfType helper. Not sure why that particular helper causes this issue, we’ll keep digging and see what else we can find.

However, we’ve managed to find a couple of workarounds. One workaround we’ve managed to find is to not use extends Document. Rewriting fourth.ts to the below works fine:

import { Schema, Document, model } from "mongoose";
  
const FourthSchema = new Schema({
  name: { type: String, required: true }
});

export interface IFourthSchema { // <-- remove `extends Document`
  name: string;
}

const Fourth = model<IFourthSchema>("Fourth", FourthSchema);
export default Fourth;

Based on our experience working with TypeScript so far, we recommend not using extends Document anymore, so this change isn’t unreasonable.

Another workaround is to use PopulatedDoc<>. For example, below is a third.ts that compiles successfully:

import { Schema, Document, model, PopulatedDoc } from "mongoose";
import { IFourthSchema } from "./fourth";

const ThirdSchema = new Schema({
  name: { type: String, required: true },
  fourthSchemaObject: {
    type: Schema.Types.ObjectId,
    ref: "Fourth"
  }
});

export interface IThirdSchema extends Document {
  name: string;
  fourthSchemaObject: PopulatedDoc<IFourthSchema>; // <-- `fourthSchemaObject` can be either ObjectId or `FourthSchema` subdoc
}

const Third = model<IThirdSchema>("Third", ThirdSchema);
export default Third;

Which is how we recommend expressing populated docs in our soon-to-be released TypeScript populate docs (see #10212) .

0reactions
vkarpov15commented, May 16, 2021

Fixed by allowing any for all update operators, which is something we’ve been meaning to do anyway.

Read more comments on GitHub >

github_iconTop Results From Across the Web

“Type instantiation is excessively deep and possibly infinite ...
Actual behavior: I'm getting this: Type instantiation is excessively deep and possibly infinite.ts(2589).
Read more >
how to ignore "Type instantiation is excessively deep and ...
After update to Typescript 3.5 i'm getting a lot of "Type instantiation is excessively deep and possibly infinite.ts(2589)" errors.
Read more >
TypeScript. Type instantiation is excessively deep ... - Ilya Zykin
I've just started a migration to TypeScript. I see many unknown and not obvious ... Type instantiation is excessively deep and possibly infinite.ts(2589)....
Read more >
Type instantiation is excessively deep and possibly infinite ...
Getting `Type instantiation is excessively deep and possibly infinite` errors whenever I pass MongoClient as a parameter in my code after ...
Read more >
Documentation - TypeScript 4.5
error: Type instantiation is excessively deep and possibly infinite. type Test = Unpack<InfiniteBox<number>>;. The above example is intentionally simple and ...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found