【问题标题】:Mongoose & TypeScript - Property '_doc' does not exist on type 'IEventModel'Mongoose 和 TypeScript - 类型“事件模型”上不存在属性“_doc”
【发布时间】:2019-11-05 13:26:03
【问题描述】:

我正在通过我正在学习的课程学习一些 JavaScript 后端编程。它专注于 ExpressJS、MongoDB 和 GraphQL。因为我喜欢让自己的事情更具挑战性,所以我决定在完成所有 TypeScript 课程的同时复习我的 TypeScript。

无论如何,我使用的是 mongoose 和 @types/mongoose 的 5.5.6 版本。这是我的数据库记录类型的界面:

export default interface IEvent {
    _id: any;
    title: string;
    description: string;
    price: number;
    date: string | Date;
}

然后我像这样创建猫鼬模型:

import { Document, Schema, model } from 'mongoose';
import IEvent from '../ts-types/Event.type';

export interface IEventModel extends IEvent, Document {}

const eventSchema: Schema = new Schema({
    title: {
        type: String,
        required: true
    },
    description: {
        type: String,
        required: true
    },
    price: {
        type: Number,
        required: true
    },
    date: {
        type: Date,
        required: true
    }
});

export default model<IEventModel>('Event', eventSchema);

最后,我为 GraphQL 突变编写了以下解析器:

createEvent: async (args: ICreateEventArgs): Promise<IEvent> => {
            const { eventInput } = args;
            const event = new EventModel({
                title: eventInput.title,
                description: eventInput.description,
                price: +eventInput.price,
                date: new Date(eventInput.date)
            });
            try {
                const result: IEventModel = await event.save();
                return { ...result._doc };
            } catch (ex) {
                console.log(ex); // tslint:disable-line no-console
                throw ex;
            }
        }

我的问题是 TypeScript 给了我一个错误,即“._doc”不是“结果”的属性。确切的错误是:

error TS2339: Property '_doc' does not exist on type 'IEventModel'.

我不知道我做错了什么。我已经多次查看文档,似乎我应该在这里拥有所有正确的 Mongoose 属性。暂时我将把属性添加到我自己的界面中,只是为了继续课程,但我更希望在这里帮助确定正确的解决方案。

【问题讨论】:

    标签: mongodb typescript mongoose


    【解决方案1】:

    interface MongoResult {
      _doc: any
    }
    
    export default interface IEvent extends MongoResult {
        _id: any;
        title: string;
        description: string;
        price: number;
        date: string | Date;
    }

    那么您仍然需要处理将 _doc 转换回您自己的 IEvent...

    【讨论】:

      【解决方案2】:

      将类型为 any_doc 添加到您的自定义模型界面

      interface IUser extends Document {
       ...
       _doc: any
      }
      

      这里有一个完整的例子https://github.com/apotox/express-mongoose-typescript-starter

      【讨论】:

        【解决方案3】:

        这可能是一个较晚的答案,但适用于所有搜索此问题的人。

        inteface DocumentResult<T> {
            _doc: T;
        }
        
        interface IEvent extends DocumentResult<IEvent> {
            _id: any;
            title: string;
            description: string;
            price: number;
            date: string | Date;
        }
        

        现在,当您调用 (...)._doc 时,_doc 将属于 _doc 类型,vscode 将能够对您的类型进行干预。只是一个通用的声明。此外,您可以将其包含在具有 IEvent 类型的 IEvent 中,而不是创建用于保存该属性的接口。

        【讨论】:

          【解决方案4】:

          当我总是在 mongoose 旁边使用 typescript 时,我会这样做, 首先我们应该为模式和模型定义接口:

          export interface IDummy {
            something: string;
            somethingElse: string;
          }
          
          export interface DummyDocument extends IDummy, mongoose.Document {
            createdAt: Date;
            updatedAt: Date;
            _doc?: any
          }
          

          第二个我们应该创建模式:

          const DummySchema = new mongoose.Schema<DummyDocument>({
            something: String,
            somethingElse: String,
          })
          

          最后我们将使用导出模型模式将我们的模型作为模块从文件中导出:

          export const DummyModel = mongoose.model<DummyDocument>
          

          现在问题已经解决,您不会看到打字稿错误,我们已经手动将 _doc 附加到我们的模型中,并在泛型的帮助下使用泛型。

          【讨论】:

            【解决方案5】:

            由于某些原因,@types/mongoose lib 中没有包含返回类型的结构。因此,每次您想要解构返回对象时,您都会收到一个错误,即在文档和自定义类型的接口签名中未定义变量。我猜这应该是某种错误。

            解决方案是返回结果本身,它会自动返回接口(IEvent)中定义的数据,没有元数据。

            ...    
            try {
                const result = await event.save();
                            return result;
                        } catch (ex) {
                            throw ex;
                        }
            ...
            

            【讨论】:

              猜你喜欢
              • 2017-07-15
              • 2021-06-22
              • 2023-04-02
              • 2018-08-17
              • 1970-01-01
              • 2023-02-06
              • 2017-08-15
              • 1970-01-01
              • 2019-06-28
              相关资源
              最近更新 更多