Skip to content

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

Closed
@qqilihq

Description

@qqilihq

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;

Metadata

Metadata

Assignees

No one assigned

    Labels

    typescriptTypes or Types-test related issue / Pull Request

    Type

    No type

    Projects

    No projects

    Milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions