【问题标题】:mongoose query helpers in typescript: property does not exist on type Query打字稿中的猫鼬查询助手:查询类型上不存在属性
【发布时间】:2021-07-16 20:34:41
【问题描述】:

基于mongoose的documentation,我尝试创建一个可链接的byYear查询助手方法如下:

import * as mongoose from 'mongoose'
import { IMovie } from '../interfaces/movies'

export interface MovieDocument extends IMovie, mongoose.Document {}

const schema = new mongoose.Schema({
    id: {
        type: String,
        required: [true, 'Missing ID'],
        index: { unique: true },
    },
    title: { type: String, required: [true, 'Missing title'] },
    year: Number,
    director: String,
    actor: [String],
})

schema.query.byYear = function (year) {
    return this.find({ year: year })
}

export const Movie = mongoose.model<MovieDocument>(
    'Movies',
    schema,
    'Movies'
)

其中IMovie 是一个简单的interface,具有与schema 相同的字段。

然后我尝试使用我的查询助手:

Movie.find().byYear(year).then(movies => {
    console.log('found these movies:', movies)
}).catch(err => {
    console.log('error:' + err)
})

但我得到Property 'byYear' does not exist on type 'Query&lt;MovieDocument[], MovieDocument, {}&gt;'Movie.find().byYear() 部分。尽管如此,代码似乎可以工作,但似乎由于输入不足,VS Code 没有意识到Movie.find() 返回的Query 实际上确实 有一个byYear 方法。我该如何正确地做到这一点?


2021-05-02 更新:我应该更多地强调我提供的代码工作很漂亮。我的问题和问题的问题更适合如何在 TypeScript 中正确“输入”它,或者仅仅是为什么会发生错误。

【问题讨论】:

  • 并非如此。在尝试确切回答该问题的内容时,我得到Type '{ byYear(this: mg.DocumentQuery&lt;any, MovieDocument&gt;, year: number): mg.Query&lt;MovieDocument[], MovieDocument, {}&gt;; }' is not assignable to type '{ [name: string]: &lt;T extends any = any&gt;(this: T, ...args: any[]) =&gt; any; }'. Property 'byYear' is incompatible with index signature.(这是我的签名:byYear(this: mg.DocumentQuery&lt;any, MovieDocument&gt;, year: number))。链接的 PR 已合并,我有最新版本。可能相关:github.com/DefinitelyTyped/DefinitelyTyped/issues/23132

标签: node.js mongodb typescript mongoose typescript-typings


【解决方案1】:

你应该这样做

Movie.find().byYear(year).exec((err, movies) => {
  if (err) {
        console.log('error:' + err)
  } else {
        console.log('found these movies:', movies)
  }
})

基本上你应该使用.exec .then 方法。
你可以在这里找到更多参考https://mongoosejs.com/docs/guide.html#query-helpers

【讨论】:

  • 谢谢,但不幸的是,这无济于事。我不明白为什么不应该使用.then(尽管链接的文档给出了.exec 的使用示例),但无论如何,我描述的错误是关于@987654328 返回的对象的byYear 属性@找不到。无关紧要,.byYear() 调用之后会发生什么。此外,正如我所说,代码有效,这只是 VS Code 为我的代码提供的错误。
【解决方案2】:

你需要像下面这样导出它

  export interface MovieDocument extends IMovie, mongoose.Document {
    }
    
    const schema = new mongoose.Schema({
        id: {
            type: String,
            required: [true, 'Missing ID'],
            index: { unique: true },
        },
        title: { type: String, required: [true, 'Missing title'] },
        year: Number,
        director: String,
        actor: [String],
    })
    
    schema.query.byYear = function(year){
        return this.find({ year: year });
    }
    
    const Movie = mongoose.model<MovieDocument>(
        'Movies',
        schema
    );

module.exports = Movie; // this file will i have saved it as movie.ts extension

并且像这样在助手中访问 确保在导入时使用 require,我已经测试过它并且它工作正常

const Movie = require('./models/movie'); 

Movie.find().byYear(2020).then((movies: any) => {
    console.log('found these movies:', movies)
}).catch((err: any) => {
    console.log('error:' + err)
})

【讨论】:

  • 你测试过你的答案吗?对我来说,您使用在集合级别操作的byYear 方法扩展文档接口似乎没有什么意义(应该是在模型上调用的方法,而不是模型的实例,即文档)。我不明白你想如何在单个 MovieDocument 实例上执行查询......此外,文档清楚地显示了一个非常不同的示例用法,它 确实 实际上工作(你提供的内容失败了byYear is not a function 但我认为一开始在逻辑上是有缺陷的)。
猜你喜欢
  • 2019-03-22
  • 2021-02-12
  • 2019-04-06
  • 1970-01-01
  • 2021-02-23
  • 2021-09-10
  • 2019-10-06
  • 2023-01-23
  • 1970-01-01
相关资源
最近更新 更多