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: $assertPopulated does not preserve the correct type of the document #12234

Closed
2 tasks done
ajwootto opened this issue Aug 8, 2022 · 2 comments
Closed
2 tasks done
Labels
typescript Types or Types-test related issue / Pull Request
Milestone

Comments

@ajwootto
Copy link

ajwootto commented Aug 8, 2022

Prerequisites

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

Mongoose version

6.5.1

Node.js version

16.13.2

MongoDB server version

5.x

Description

The recently-added $assertPopulated helper currently does not preserve the "document" type of a document instance, and instead just turns it into the underlying interface type:

import { Schema, model, connect, Types } from 'mongoose'

interface NestedChild {
    name: string
    _id: Types.ObjectId
}
const nestedChildSchema: Schema = new Schema({ name: String })

interface Parent {
    nestedChild: Types.ObjectId
    name?: string
}

const ParentModel = model<Parent>('Parent', new Schema({
    nestedChild: { type: Schema.Types.ObjectId, ref: 'NestedChild' },
    name: String
}))

const NestedChildModel = model<NestedChild>('NestedChild', nestedChildSchema)

async function run() {
    await connect('mongodb://localhost:27017/')
    const parent = (new ParentModel({
        nestedChild: new NestedChildModel({ name: 'test' }),
        name: 'Parent'
    })).$assertPopulated<{nestedChild: NestedChild}>('nestedChild')

    // works, assertPopulated makes sure `parent` has a nestedChild field correctly typed
    console.log(parent.nestedChild.name)

   // doesn't work, parent is no longer a Document 
    await parent.save()
}

run()

From what I can tell, changing the definition from this:

$assertPopulated<Paths = {}>(paths: string | string[]): Omit<DocType, keyof Paths> & Paths;

to this:

$assertPopulated<Paths = {}>(paths: string | string[]): Omit<this, keyof Paths> & Paths;

would fix the problem.

Steps to Reproduce

See code snippet

Expected Behavior

I would expect that when working with a document instance, $assertPopulated should preserve the document type so that it's possible to save it etc.

@vkarpov15
Copy link
Collaborator

We'll look into this, however, we switched this -> DocType for performance reasons. Using this caused some serious slowdowns in tsc.

@vkarpov15 vkarpov15 added this to the 6.5.4 milestone Aug 22, 2022
@vkarpov15
Copy link
Collaborator

I switched this back because I confirmed that it doesn't cause a performance regression anymore. I think the performance issues with this were exacerbated by some of the issues we fixed in #10349.

Fix will be in 6.5.4 👍

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