我知道这可能是太基本了,但我不记得如何正确地做到这一点。我想声明一个Mongoose文档使用VS Code智能感知来检索数据。
现在,document
被声明为any
,因为findById()
返回any
:
const document = await MyModel.findById(docId);
因此,每当我想调用document.updateOne()
之类的东西时,我都没有开启智能感知。
我试过使用如下命令:
import { Model, Document } from 'mongoose';
...
const document: Model<Document> = await MyModel.findById(docId);
但这并不能让我像document.title
或任何其他一样直接引用内部属性。
那么,如何正确地声明document
呢?
您的MyModel
具有某种文档类型,extends
(猫鼬Document
)类型并添加了可能添加了自己的一些属性。这就是你想要使用的泛型。
在检索文档时不需要设置泛型(<Document>
),而是希望在MyModel
对象本身上设置泛型,以便typescript可以推断出findById
和任何其他方法的正确类型。所以你要在创建MyModel
的地方处理这个
interface MyDocument extends Document {
title: string;
}
const MyModel = mongoose.model<MyDocument>(name, schema);
现在document
被推断为类型MyDocument | null
:
const document = await MyModel.findById(docId);
您提到的updateOne
方法应该开箱运行,一旦您使用findById
方法,在这个时间点(2023年2月)。
const myDoc = await MyModel.findById(docId);
myDoc.updateOne(/* something */);
如果您仍然有麻烦,并且需要在其他地方键入文档,我建议使用HydratedDocument
和HydratedDocumentFromSchema
泛型。
type Doc1 = HydratedDocument<typeof MyModel>;
type Doc2 = HydratedDocument<typeof MySchema>;
// or
type Doc2 = HydratedDocument<typeof MyModela.schema>;
你可以使用这些符号中的任何一个,这取决于你有什么可用的符号。
这对我有用:
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>);
};
最新推荐的文档输入方式是使用HydratedDocument
:
import { HydratedDocument } from "mongoose";
interface Animal {name: string}
const animal: HydratedDocument<Animal> = AnimalModel.findOne( // ...
https://mongoosejs.com/docs/typescript.html