首页 > 解决方案 > 如何在猫鼬模型上定义实例/文档方法,而不将它们包含在文档界面中

问题描述

使用 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>接口。

那么,如果我们不应该将它们放在文档界面上,我们应该如何定义它们以便打字稿可以允许访问?

标签: typescriptmongodbmongoosemongoose-schema

解决方案


推荐阅读