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

TypeScript error when passing { _id: ids } or { _id: arrayOfDocs } to FilterQuery #10826

Closed
ahmedelshenawy25 opened this issue Sep 30, 2021 · 2 comments
Labels
typescript Types or Types-test related issue / Pull Request
Milestone

Comments

@ahmedelshenawy25
Copy link
Contributor

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

What is the current behavior?
TypeScript compilation error if _id is given an array of ids or documents in FilterQuery

Type '(Document<any, any, IBook> & IBook & { _id: string | ObjectId; })[]' is not assignable to type 'Condition<string | ObjectId> | undefined'.
  Type '(Document<any, any, IBook> & IBook & { _id: string | ObjectId; })[]' is not assignable to type 'string'
Type '(string | ObjectId)[]' is not assignable to type 'Condition<string | ObjectId> | undefined'.
  Type '(string | ObjectId)[]' is not assignable to type 'string'.

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

import mongoose, { Types } from 'mongoose';

interface IBook {
  _id: Types.ObjectId | string;
  name: string;
}

async function run() {
  await mongoose.connect('mongodb://localhost:27017/test');

  const bookSchema = new mongoose.Schema<IBook>({
    name: { type: String, required: true }
  });

  const Book = mongoose.model<IBook>('Book', bookSchema);

  await Book.create([{ name: 'aaa' }, { name: 'aaa' }]);

  const books = await Book.find({});
  const booksIds = books.map((book: IBook) => book._id);

  await Book.updateMany({ _id: books }, { name: 'bbb' });
  await Book.updateMany({ _id: booksIds }, { name: 'ccc' });

  console.log('Done');
}

run().catch(console.error);
{
  "compilerOptions": {
    "target": "ES6",
    "module": "commonjs",
    "esModuleInterop": true,
    "forceConsistentCasingInFileNames": true,
    "strict": true,
    "skipLibCheck": true
  }
}

What is the expected behavior?
It should pass compilation since mongoose transforms FilterQuery into { _id :{ $in: ids} }

What are the versions of Node.js, Mongoose and MongoDB you are using? Note that "latest" is not a version.
Node.js: v14.15.5
Mongoose: v6.0.8
MongoDB: v4.4.3

@ahmedelshenawy25 ahmedelshenawy25 changed the title TypeScript error when passing { _id: ids } or { _id: arrayOfDocs } to FilterQuery` TypeScript error when passing { _id: ids } or { _id: arrayOfDocs } to FilterQuery Sep 30, 2021
@IslandRhythms IslandRhythms added the help This issue can likely be resolved in GitHub issues. No bug fixes, features, or docs necessary label Oct 1, 2021
@IslandRhythms
Copy link
Collaborator

So this isn't a bug. The way updateMany() works is that it will find all documents that match a filter, the 1st parameter, and change it to match what was given in the 2nd parameter. When you do {_id: books}, what you're doing is passing in an array because that is what find() returns when given no arguments. This is why if you were to do {_id: books[0]._id} you would get no error. It seems from the script you want to update all the docs with the new name so just omit the 1st parameter from the updateMany() call and it will do what you want. So do updateMany({}, {name: 'bbb'})

@ahmedelshenawy25
Copy link
Contributor Author

I think there's a bit of misunderstanding. So if you add // @ts-expect-error before each update and run the script with mongoose.set('debug', true), you will find that mongoose transforms both of these filter queries into { _id: { $in: [objectIds] } } and since mongoose allows this kind of behavior TypeScript should compile without any errors

import mongoose, { Types } from 'mongoose';

interface IBook {
  _id: Types.ObjectId | string;
  name: string;
}

async function run() {
  await mongoose.connect('mongodb://localhost:27017/test');

  mongoose.set('debug', true);

  const bookSchema = new mongoose.Schema<IBook>({
    name: { type: String, required: true }
  });

  const Book = mongoose.model<IBook>('Book', bookSchema);

  await Book.create([{ name: 'aaa' }, { name: 'aaa' }, { name: 'aaa' }, { name: 'aaa' }]);

  const books = await Book.find({}).limit(2);
  const booksIds = books.map((book: IBook) => book._id);

  // @ts-expect-error
  await Book.updateMany({ _id: books }, { name: 'bbb' });
  // @ts-expect-error
  await Book.updateMany({ _id: booksIds }, { name: 'ccc' });

  console.log('Done');
}

run().catch(console.error);

image

@IslandRhythms IslandRhythms added typescript Types or Types-test related issue / Pull Request and removed help This issue can likely be resolved in GitHub issues. No bug fixes, features, or docs necessary labels Oct 1, 2021
@vkarpov15 vkarpov15 added this to the 6.0.12 milestone Oct 1, 2021
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
Development

No branches or pull requests

3 participants