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.

findByIdAndUpdate() type error

See original GitHub issue

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

What is the current behavior? There seems to be a type error when using the interface pattern described here: Complete guide for Typescript with Mongoose for Node.js

No overload matches this call.
  The last overload gave the following error.
    Argument of type 'IProduct' is not assignable to parameter of type 'UpdateQuery<IProductDoc>'.
      Type 'IProduct' is not assignable to type 'ReadonlyPartial<_UpdateQueryDef<LeanDocument<IProductDoc>>>'.
        Types of property 'brand' are incompatible.
          Type 'Record<string, any> | ObjectId' is not assignable to type 'string | ObjectId | undefined'.
            Type 'Record<string, any>' is not assignable to type 'string | ObjectId | undefined'.
              Type 'Record<string, any>' is not assignable to type 'string'. ts(2769)

index.d.ts(972, 5): The last overload is declared here.

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

Here’s how I actually implemented it:

// Custom mongoose base document
export interface IMongooseBaseDoc {
  _id: Types.ObjectId;
  createdAt?: Date;
  updatedAt?: Date;
}

export interface IProduct {
  brand: Types.ObjectId | Record<string, any>; //? Need fix
  // ...
}

export interface IProductDoc extends IProduct, IMongooseBaseDoc {
  images: Types.Array<IImage>;
  brand: IBrandDoc["_id"]; // another model
}

export interface IProductPopulatedDoc extends IProductDoc {
  brand: IBrandDoc; // this is why it needs to be `Record<string, any>` or typescript will complain
}

export type TSchema<T> = Record<
  keyof T,
  SchemaTypeOptions<any> | Schema | SchemaType
>

// ...
const ProductSchema = new Schema<TSchema<IProductDoc>>(...)

export default model<TSchema<IProductDoc>>("Product", ProductSchema);

The TSchema used is from https://github.com/Automattic/mongoose/issues/9715 in courtesy of https://github.com/Automattic/mongoose/issues/9715#issuecomment-816146242. The IBrandDoc is just something similar to IProductDoc but on another model. I made my own working base document as stated in Mongoose Docs on TypeScript Support.

There’s nothing really wrong with the inheritance pattern described in the blogpost. It does work when an interface has no references to another model and the typesetting is sufficiently strong. However, when it is used in findByIdAndUpdate(), it creates the type error above. As far as I know, findOneAndUpdate(), updateOne(), and updateMany() also produces similar errors.

const data: IProduct = {
  brand: args.brand,
  // ...
};

const savedProduct = await new Product(data).save(); // works!

const updatedProduct = await Product.findByIdAndUpdate(
  args._id,
  data, //! Error: Type 'Record<string, any>' is not assignable to type 'string'. ts(2769)
  options
);

My tsconfig.json:

{
  "compilerOptions": {
    "target": "esnext",

    "module": "commonjs",
    "rootDir": "./",
    "moduleResolution": "node",
    "baseUrl": "./src",
    "typeRoots": ["@types"],

    "declaration": true,
    "declarationMap": true,
    "sourceMap": true,
    "outDir": "./dist",
    "esModuleInterop": true,
    "forceConsistentCasingInFileNames": true,

    "strict": true,
    "skipLibCheck": true
  },
  "exclude": ["./dist"]
}

What is the expected behavior? I don’t really know if I’m doing something wrong there, but it should work as is given that the IProduct interface works perfectly with the other model methods. Interfaces without references to other models work like a charm.

A temporary workaround would be to cast the data object above to any (e.g., <any>data) when using it as an argument in findByIdAndUpdate(), but I don’t know the future implications for this. I wonder if the blogpost is outdated now that Mongoose v6 is out.

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

Node: v17.1.0 Mongoose: v6.0.12 MongoDB: v4.1.4 (did not explicitly install, it is a dep from when Mongoose was installed)

Update: Took a little breather and it turns out I just needed to use the IProductDoc instead of just the IProduct since updating meant that it assumes it’s already a saved document. In other words, it already has an _id and such. No errors ever since. My bad. I guess the takeaway here is that when the going gets tough, just don’t forget to take a break sometimes.

Update 11/20/21: I retract my earlier revelation. I do in fact need data to be just the plain IProduct instead of the IProductDoc. I just found out I can’t append the _id in the update params for use in findByIdAndUpdate() as it gives the expected "_id" to be unique error, so using IProductDoc gives object creation type errors. Found something similar on https://github.com/Automattic/mongoose/issues/10689.

Issue Analytics

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

github_iconTop GitHub Comments

1reaction
vkarpov15commented, Dec 16, 2021

If it works in 6.1.1 then this issue should be ok to close

0reactions
decanTymecommented, Dec 11, 2021

I just upgraded from mongoose 6.0.7 to 6.1.1 and now everywhere I use findOneAndUpdate is showing this No overload matches this call. as mentioned in the OP.

Strange, upgrading to 6.1.1 for me actually removed the error. I can confirm it now runs fine from both my codebase (local and live) and codesandbox without any casting. I guess I still can’t close this one then.

Read more comments on GitHub >

github_iconTop Results From Across the Web

node.js - Determine Mongoose findByIdAndUpdate() error type
Determine Mongoose findByIdAndUpdate() error type ... findById() first to determine 404 and then can use model.update() to determine 422.
Read more >
mongoose.Model.findByIdAndUpdate JavaScript and Node.js ...
var findByIdAndUpdate = function(id, data, callback){ roomModel. ... function (err, oldMedium) { if (err) err.type = 'database'; callback(err, ...
Read more >
findOneAndUpdate is not a function - Error
TypeError : newDocument.findOneAndUpdate is not a function. Here is extract of my code: var keystone = require('keystone'),. async = require('async'),.
Read more >
How to Use the Mongoose findByIdAndUpdate Method
The findByIdAndUpdate() method is specifically used to find a document by providing the value of the auto-generated _id field and then update ...
Read more >
mongoose findbyid and update error in type object field
Beyond that, you'll need to post your schema code in order for us to help you tract down any CastErrors that remain. Open...
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