typescript - 如何在猫鼬模型上定义实例/文档方法,而不将它们包含在文档界面中
问题描述
在使用 mongoose 和 typescriptmongoose.Document
的官方文档中,关于在提供类型定义时扩展类型,它指出:
这种方法有效,但我们建议您的文档界面不要扩展 Document。使用 extends Document 使得 Mongoose 很难推断查询过滤器、精简文档和其他情况下存在哪些属性。
我们建议您的文档界面包含架构中定义的属性,并与您的文档在 MongoDB 中的外观保持一致。虽然您可以将实例方法添加到您的文档界面,但我们不建议您这样做。
关于第二段的最后一行,如果建议不要在文档接口中包含实例/文档方法——我们应该如何提供这些信息?如果没有在文档接口上定义这些方法,typescript 会抛出一个错误,即Property <insert method name> does not exist on type <insert document types>
.
例如,考虑以下用户定义:
// user.model.ts
import { model, Schema } from 'mongoose';
import { UserDoc } from '../types/user.d.ts';
const userSchema = new Schema<UserDoc, Model<UserDoc>, UserDoc>({
firstName: { type: String, required: true },
lastName: { type: String, required: true },
email: { type: String, required: true, unique: true, lowercase: true },
password: { type: String, required: true, trim: true }
});
userSchema.virtual('fullName').get(function (this: UserDoc) {
return `${this.firstName} ${this.lastName}`
});
userSchema.method('getFullName', function () {
return `${this.firstName} ${this.lastName}`
})
export default model<UserDoc, Model<UserDoc>>('User', userSchema)
UserDoc
接口定义如下:
export interface UserDoc {
firstName: string;
lastName: string;
email: string;
password: string;
}
如果没有在接口上显式定义fullName
虚拟属性或getFullName
实例方法UserDoc
,则两者都无法访问。
例如,考虑以下快速路由处理程序来注册新用户:
import { RequestHandler } from 'express';
import User from '../models/user.model.ts'; // The model as defined in the above userSchema
const registerUserHandler: RequestHandler = async (req, res, next) => {
const { firstName, lastName, email, password } = req.body;
if (await User.exists({ email })) {
return res.status(400).json('Email already exists')
}
const newUser = await User.create({ firstName, lastName, email, password });
console.log(newUser.fullName) // This will cause typescript error
console.log(newUser.getFullName()) // This will cause typescript error
return res.status(201).json('User created')
}
但是,如果将UserDoc
接口扩展为包含fullName
虚拟和getFullName
方法,则打字稿不会出错并允许访问。
在查看静态方法的官方文档时,它声明您必须包含这些并扩展mongoose.Model<T>
接口。
那么,如果我们不应该将它们放在文档界面上,我们应该如何定义它们以便打字稿可以允许访问?
解决方案
推荐阅读
- express - 使用 Postman 测试请求未定义
- c# - 在目录 C# 中查找游戏启动器可执行文件
- c++ - 是否可以回调模板类的成员?
- amazon-web-services - 使用 Terraform 在 AWS 中创建 Lambda 函数时无法加载文件名
- javascript - react-modal 的奇怪行为
- apache-spark - 用于 Spark Streaming 的 Kafka 连接器版本
- python-3.x - 使用 from_logs 生成器删除某个月份的所有消息
- r - 如何从字母向量中枚举字符串
- excel - 如何使用 VB.net 读取作为 COM__Object 传递的自定义 VBA 类对象的成员?(UIPath)
- linux - Kubernetes 工作节点 cpu 和内存请求始终保持为零