Mongoose 和 TypeScript - 类型“事件模型”上不存在属性“_doc”

Posted

技术标签:

【中文标题】Mongoose 和 TypeScript - 类型“事件模型”上不存在属性“_doc”【英文标题】:Mongoose & TypeScript - Property '_doc' does not exist on type 'IEventModel' 【发布时间】: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 属性。暂时我将把属性添加到我自己的界面中,只是为了继续课程,但我更希望在这里帮助确定正确的解决方案。

【问题讨论】:

【参考方案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;
            
...

【讨论】:

以上是关于Mongoose 和 TypeScript - 类型“事件模型”上不存在属性“_doc”的主要内容,如果未能解决你的问题,请参考以下文章

如何在nestjs mongoose typescript中引用嵌套文档

TypeScript 的 Mongoose loadClass 问题

typescript 使用TypeScript和MongoDb的Mongoose示例

typescript 使用TypeScript和MongoDb的Mongoose示例

typescript 使用TypeScript和MongoDb的Mongoose示例

Mongoose 的 loadClass() 和 TypeScript