Reputation: 3474
I know maybe this is far too basic but I can't recall how to do this properly. I want to declare a Mongoose document to use VS Code IntelliSense for retrieve data.
Right now, document
is declared as any
since findById()
returns any
:
const document = await MyModel.findById(docId);
So, whenever I want to call to something like document.updateOne()
I don't have intelliSense on.
I have tried using something like:
import { Model, Document } from 'mongoose';
...
const document: Model<Document> = await MyModel.findById(docId);
But this don't give me the ability to refer internal attributes directly like document.title
or any other.
So, what is the proper way to declare document
?
Upvotes: 3
Views: 4371
Reputation: 42288
Your MyModel
has some sort of document type that extends
the Mongoose Document
type and likely adds some properties of its own. That's the generic that you want to use.
Instead of setting the generic (<Document>
) when you retrieve the document, you want to set the generic on the MyModel
object itself so that the Typescript will infer the correct type for findById
and for any other methods. So you want to handle this at the place where you create MyModel
.
interface MyDocument extends Document {
title: string;
}
const MyModel = mongoose.model<MyDocument>(name, schema);
Now the document
is inferred to be type MyDocument | null
here:
const document = await MyModel.findById(docId);
Upvotes: 3
Reputation: 3214
The method you mentioned updateOne
should work out of the box, once you use the findById
method, at this point in time (Feb 2023).
const myDoc = await MyModel.findById(docId);
myDoc.updateOne(/* something */);
In case you still have trouble, and need to type the Document elsewhere, I would suggest the HydratedDocument
and HydratedDocumentFromSchema
generic types.
type Doc1 = HydratedDocument<typeof MyModel>;
type Doc2 = HydratedDocument<typeof MySchema>;
// or
type Doc2 = HydratedDocument<typeof MyModela.schema>;
You can use any of these depending on what symbols you have available to you.
Upvotes: 1
Reputation: 1814
The new recommended way of typing documents is using HydratedDocument
:
import { HydratedDocument } from "mongoose";
interface Animal {name: string}
const animal: HydratedDocument<Animal> = AnimalModel.findOne( // ...
https://mongoosejs.com/docs/typescript.html
Upvotes: 3
Reputation: 897
This worked for me:
export const findPostById = async (postId: any): Promise<HydratedDocument<typeof Post.schema.obj>> => {
const post = await Post.findById(postId);
return (post as HydratedDocument<typeof Post.schema.obj>);
};
Upvotes: 1