Typescript 中的 Mongoose 静态模型定义

Posted

技术标签:

【中文标题】Typescript 中的 Mongoose 静态模型定义【英文标题】:Mongoose static Model definitions in Typescript 【发布时间】:2018-01-18 17:31:25 【问题描述】:

我创建了一个 Mongoose Schema 并为模型添加了一些静态方法,命名为 Campaign。

如果我 console.log 活动,我可以看到上面存在的方法。问题是我不知道在哪里添加这些方法,以便 Typescript 也知道它们。

如果我将它们添加到我的 CampaignModelInterface,它们仅可用于模型实例(或者至少 TS 认为它们是可用的)。

campaignSchema.ts

  export interface CampaignModelInterface extends CampaignInterface, Document 
      // will only show on model instance
  

  export const CampaignSchema = new Schema(
      title:  type: String, required: true ,
      titleId:  type: String, required: true 
      ...etc
  )

  CampaignSchema.statics.getLiveCampaigns = Promise.method(function ()
      const now: Date = new Date()
      return this.find(
           $and: [startDate: $lte: now , endDate: $gte: now ]
      ).exec()
  )

  const Campaign = mongoose.model<CampaignModelInterface>('Campaign', CampaignSchema)
  export default Campaign

我也尝试通过 Campaign.schema.statics 访问它,但没有运气。

谁能建议如何让 TS 知道模型上存在的方法,而不是模型实例?

【问题讨论】:

【参考方案1】:

我在here 上回答了一个非常相似的问题,尽管我会回答你的问题(主要是在我的另一个答案的第三部分),因为你提供了不同的架构。有一个有用的关于 Mongoose 类型的自述文件,它相当隐蔽,但在 static methods 上有一个部分。


您描述的行为完全正常 - Typescript 被告知 Schema(描述单个文档的对象)具有称为 getLiveCampaigns 的方法。

相反,您需要告诉 Typescript 该方法在模型上,而不是模式上。完成后,您可以按照正常的 Mongoose 方法访问静态方法。您可以通过以下方式做到这一点:

// CampaignDocumentInterface should contain your schema interface,
// and should extend Document from mongoose.
export interface CampaignInterface extends CampaignDocumentInterface 
    // declare any instance methods here


// Model is from mongoose.Model
interface CampaignModelInterface extends Model<CampaignInterface> 
    // declare any static methods here
    getLiveCampaigns(): any; // this should be changed to the correct return type if possible.


export const CampaignSchema = new Schema(
    title:  type: String, required: true ,
    titleId:  type: String, required: true 
    // ...etc
)

CampaignSchema.statics.getLiveCampaigns = Promise.method(function ()
    const now: Date = new Date()
    return this.find(
        $and: [startDate: $lte: now , endDate: $gte: now ]
    ).exec()
)

// Note the type on the variable, and the two type arguments (instead of one).
const Campaign: CampaignModelInterface = mongoose.model<CampaignInterface, CampaignModelInterface>('Campaign', CampaignSchema)
export default Campaign

【讨论】:

谢谢!很惊讶我之前没有遇到过你的原始答案:) 正如你所建议的那样,能够让它工作。如果我理解正确,我现在会将所有 Schema.static 方法放在 CampaignModelInterface 上,并将所有 Schema.method 方法放在 CampaignDocumentInterface 上? 好吧,我个人将其设置为 CampaignDocumentInterface 仅包含架构(如 CampaignSchema 中定义的那样)。 CampaignInterface 包含你所有的 Schema.method 方法,CampaignModelInterface 包含你所有的 Schema.static 方法。 您也可以在CampaignDocumentInterface 中声明您的Schema.method 方法,我个人只是更喜欢分离。 确保您放弃订单:model&lt;CampaignModelInterface, CampaignInterface&gt;。这不起作用:model&lt;CampaignInterface, CampaignModelInterface&gt; @Mykola 在类型文件中的model 的definition 是function model&lt;T extends Document, U extends Model&lt;T&gt;&gt;。因此订单是model&lt;CampaignInterface, CampaignModelInterface&gt;(...)

以上是关于Typescript 中的 Mongoose 静态模型定义的主要内容,如果未能解决你的问题,请参考以下文章

带有 typescript 和 mongoose 的静态方法会:“一个接口只能扩展一个类或另一个接口。”

Typescript Mongoose - 方法/静态函数未被调用 [Kubernetes - Docker]

TypeScript 中的 Mongoose 方法范围

打字稿:猫鼬模式的静态方法

TypeScript 中的 Mongoose post hook 类型错误

Mongoose 的 loadClass() 和 TypeScript