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

Export EnforceDocument<> from TypeScript types, rename it to something more user-friendly #10843

Closed
Bene-Graham opened this issue Oct 4, 2021 · 9 comments
Labels
typescript Types or Types-test related issue / Pull Request
Milestone

Comments

@Bene-Graham
Copy link

If we take a slightly modified version of: https://mongoosejs.com/docs/typescript.html

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

interface User {
    name: string;
    email: string;
    avatar?: string;
}

const schema = new Schema<User>({
    name: { type: String, required: true },
    email: { type: String, required: true },
    avatar: String
});

const UserModel = model<User>('User', schema);

run().catch(err => console.log(err));

function print(entity: /* WHAT GOES HERE??? */) {
    console.log(`${entity._id} -- ${entity.name}`);
}

async function run(): Promise<void> {
    // 4. Connect to MongoDB
    await connect('mongodb://localhost:27017/test');

    const userEntity = await UserModel.findOne().exec();
    if(!userEntity) {
        throw new Error("userEntity is null");
    }
    
    print(userEntity);
}

the return type from findOne is

(Document<any, any, User> & User & { _id: Types.ObjectId; }) 

that seems very verbose for putting in the function signature each time I want to reference it.

I also could not find a utility type build into the type definitions. Should we create our own type to wrap this up

type DocDef<T> = (Document<any, any, T> & T & { _id: Types.ObjectId; });

or add _id to the User interface?

I am wondering what is the best practice?

Also curious what DocumentDefinition is supposed to be used for?

@IslandRhythms IslandRhythms added the help This issue can likely be resolved in GitHub issues. No bug fixes, features, or docs necessary label Oct 5, 2021
@vkarpov15
Copy link
Collaborator

Add _id: Types.ObjectId to interface User {}. We should add that to the docs.

interface User {
    _id: Types.ObjectId;
    name: string;
    email: string;
    avatar?: string;
}

@vkarpov15 vkarpov15 added docs This issue is due to a mistake or omission in the mongoosejs.com documentation and removed help This issue can likely be resolved in GitHub issues. No bug fixes, features, or docs necessary labels Oct 5, 2021
@vkarpov15 vkarpov15 added this to the 6.0.13 milestone Oct 5, 2021
@imduchy
Copy link
Contributor

imduchy commented Oct 6, 2021

How does adding _id to your model interface help here? The returned object would still be of the type Document<any, any, User> & User & { _id: Types.ObjectId; }, right? Wouldn't a utility type - as proposed by @Bene-Graham - make more sense here?

Also, if you add _id: Types.ObjectId to your model interfaces, then TypeScript will force you to supply _id also during document creation. What's the recommended way to go around it? Maybe manually creating ObjectId in the code?

User.create({
    _id: , new Types.ObjectId() // this is required
    username: "Dumbledore",
    email: "dumbledore@hogwarts.com,
    avatar: "<url>"
})

@Bene-Graham
Copy link
Author

I am guessing the utility type is the way to go, since methods like .save(), .remove(), etc are missing as well.

@vkarpov15
Copy link
Collaborator

The utility type could work. Perhaps exporting Mongoose's internal EnforceDocument<> type would help? It does what you suggest, but also adds instance methods and virtuals:

type EnforceDocument<T, TMethods, TVirtuals> = T extends Document ? Require_id<T> : (Document<any, any, T> & Require_id<T> & TVirtuals & TMethods);

@Bene-Graham
Copy link
Author

EnforceDocument does seem to do what I want.

Should the return types for find, findAll(), etc then return a EnforceDocument?

@imduchy
Copy link
Contributor

imduchy commented Oct 6, 2021

I think this is somewhat related to #10837

@Bene-Graham
Copy link
Author

@Duchynko it is defiantly related

@vkarpov15
Copy link
Collaborator

@Bene-Graham find(), findAll(), etc. return a Query instance that resolves to EnforceDocument<>

@vkarpov15 vkarpov15 changed the title [6.x] Types - What type should be used to pass a document around and have access to _id Export EnforceDocument<> from TypeScript types, rename it to something more user-friendly Oct 8, 2021
@vkarpov15 vkarpov15 added typescript Types or Types-test related issue / Pull Request and removed docs This issue is due to a mistake or omission in the mongoosejs.com documentation labels Oct 8, 2021
@imduchy
Copy link
Contributor

imduchy commented Oct 8, 2021

vkarpov15 changed the title [6.x] Types - What type should be used to pass a document around and have access to _id Export EnforceDocument<> from TypeScript types, rename it to something more user-friendly

I think this will solve #10837 as well 👍🏼

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

4 participants