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

Return type of document.depopulate() is still the populated document type #14876

Closed
2 tasks done
blowfishlol opened this issue Sep 10, 2024 · 1 comment · Fixed by #14891
Closed
2 tasks done

Return type of document.depopulate() is still the populated document type #14876

blowfishlol opened this issue Sep 10, 2024 · 1 comment · Fixed by #14891
Labels
typescript Types or Types-test related issue / Pull Request
Milestone

Comments

@blowfishlol
Copy link

blowfishlol commented Sep 10, 2024

Prerequisites

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

Mongoose version

8.6.1

Node.js version

18.19.0

MongoDB server version

6.0.15 Community

Typescript version (if applicable)

5.6.2

Description

When populating a document, and then depopulating it, the type will remain as if the document is still populated.

When testing in 8.3.1, the return type from a depopulate() method is the original document type.

Steps to Reproduce

import { type Types, Schema, connect, model } from 'mongoose';
type CarObjectInterface = {
  make: string;
  model: string;
  year: number;
  owner: Types.ObjectId;
};
const carSchema = new Schema<CarObjectInterface>({
  make: { type: String, required: true },
  model: { type: String, required: true },
  year: { type: Number, required: true },
  owner: { type: Schema.Types.ObjectId, ref: 'User' }
});

type UserObjectInterface = {
  name: string;
  age: number;
};
const userSchema = new Schema<UserObjectInterface>({
  name: String,
  age: Number
});

async function main() {
  await connect('mongodb://localhost:27017/playground');
  const Car = model<CarObjectInterface>('Car', carSchema);
  const User = model<UserObjectInterface>('User', userSchema);

  const user = await User.create({ name: 'John', age: 25 });
  const car = await Car.create({
    make: 'Toyota',
    model: 'Camry',
    year: 2020,
    owner: user._id
  });

  const populatedCar = await Car.findById(car._id)
    .populate<{ owner: UserObjectInterface }>('owner')
    .exec();

  if (!populatedCar) return;

  console.log(populatedCar.owner.name); // outputs John

  const depopulatedCar = populatedCar.depopulate();

  console.log(populatedCar.owner.name); // outputs undefined
  console.log(depopulatedCar.owner.name); // outputs undefined BUT throws type error on 8.3.1
}

main().then(() => {
  console.log('done');
});

Expected Behavior

The return value from .depopulate() method should be the depopulated type.

In the case of the reproduction script,

console.log(depopulatedCar.owner.name)

is expected to give a type error, because owner type is expected to be ObjectId

@vkarpov15 vkarpov15 added this to the 8.6.3 milestone Sep 11, 2024
@vkarpov15 vkarpov15 added the typescript Types or Types-test related issue / Pull Request label Sep 11, 2024
vkarpov15 added a commit that referenced this issue Sep 17, 2024
types(document): add generic param to depopulate() to allow updating properties
@vkarpov15
Copy link
Collaborator

With #14891 you'll be able to do doc.depopulate<{ user: ObjectId }>('user')

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

Successfully merging a pull request may close this issue.

2 participants