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) toObject on populated documents loses the structure #14441

Closed
2 tasks done
qqilihq opened this issue Mar 15, 2024 · 1 comment · Fixed by #14525
Closed
2 tasks done

(Typescript) toObject on populated documents loses the structure #14441

qqilihq opened this issue Mar 15, 2024 · 1 comment · Fixed by #14525
Labels
typescript Types or Types-test related issue / Pull Request
Milestone

Comments

@qqilihq
Copy link

qqilihq commented Mar 15, 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.2.2

Node.js version

20

MongoDB server version

5.x

Typescript version (if applicable)

5.2.2

Description

When calling toObject on a populated document (which used a type parameter in populate) the type structure is lost.

Steps to Reproduce

Based on the example from the docs:

import { Document, model, Schema, Types } from 'mongoose';

// `Parent` represents the object as it is stored in MongoDB
interface Parent {
  child?: Types.ObjectId;
  name?: string;
}
const ParentModel = model<Parent>(
  'Parent',
  new Schema({
    child: { type: Schema.Types.ObjectId, ref: 'Child' },
    name: String
  })
);

interface Child {
  name: string;
}
const childSchema: Schema = new Schema({ name: String });
const ChildModel = model<Child>('Child', childSchema);

// Populate with `Paths` generic `{ child: Child }` to override `child` path
ParentModel.findOne({})
  .populate<{ child: Child }>('child')
  .orFail()
  .then(doc => {
    // Works
    const t: string = doc.child.name;
    // **** Works not as expected ****
    const docObject = doc.toObject();
    const t2: string = docObject.child.name; // error - child is not Child
  });

Expected Behavior

I'd expect that the passed type information (ie. { child: Child }) is preserved when calling toObject.

Not sure if this can be done, so let me add a question: Are there any recommendations for a workaround? We do quite some heavy population in different combinations and I'd ideally like to infer the typings based on the already existing types.

Something like this works, but is quite tedious:

    const docObject = doc.toObject<MergeType<Parent, { child: Child }>>();
    const t2: string = docObject.child.name;
@vkarpov15 vkarpov15 added this to the 8.2.4 milestone Mar 20, 2024
@vkarpov15 vkarpov15 added the typescript Types or Types-test related issue / Pull Request label Mar 20, 2024
@vkarpov15 vkarpov15 modified the milestones: 8.2.4, 8.2.5 Mar 28, 2024
@vkarpov15 vkarpov15 modified the milestones: 8.3.1, 8.3.2 Apr 8, 2024
@vkarpov15 vkarpov15 modified the milestones: 8.3.2, 8.3.3 Apr 15, 2024
vkarpov15 added a commit that referenced this issue Apr 24, 2024
types(query+populate): apply populate overrides to doc `toObject()` result
@qqilihq
Copy link
Author

qqilihq commented Apr 26, 2024

@vkarpov15 Thank you - looking forward to give it a try!

vkarpov15 added a commit that referenced this issue May 9, 2024
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