Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Mongoose Property 'x' does not exist on type 'Document'

The ts compiler says that none of the properties exist on type 'Document'.

It seems that because of this none of the properties on the model can be set. If I print a user object to the console all I get is {"_id":"long hex id number"}

My model is configured as follows:

users.ts

import * as mongoose from 'mongoose';
import * as crypto from 'crypto';
import * as jwt from 'jsonwebtoken';

var userSchema = new mongoose.Schema({
    email: {
        type: String,
        unique: true,
        required: true
    },
    firstMidname: {
        type: String,
        required: true
    },
    lastName: {
        type: String,
        required: true
    },
    hash: String,
    salt: String
});

userSchema.methods.setPassword = setPassword;


userSchema.methods.validPassword = validPassword;

userSchema.methods.generateJwt = generateJwt;

export = mongoose.model('User', userSchema);

Api connection point api.ts

import * as express from    'express';
import * as mongoose from   'mongoose';
import * as passport from   'passport';

var User = mongoose.model('User');

var router = express.Router();

router.post('/', createUser);

function createUser(req, res){
var user = new User();
    console.log(user);
    user.firstMidName = req.body.firstName;
    user.lastName = req.body.lastName;
    user.setPassword(req.body.password);

    user.save((err) => {
        console.log("saving user");
        var token;
        token = user.generateJwt();
        res.status(200);
        res.json({
            'token': token
        });
    });
}

export = router;

How can I fix or troubleshoot this issue? Nothing in the user.save block executes.

EDIT: The two things seem to be unrelated. I can now save to the database however the typescript error persists. Is this expected behaviour?

like image 694
xerotolerant Avatar asked Feb 16 '17 13:02

xerotolerant


3 Answers

Fixed this by adding interface upon declaration of schema

interface UserInterface extends Document {
  email: string;
}

const User = new Schema<UserInterface>({
  email: String;
})
like image 132
Justin Herrera Avatar answered Sep 20 '22 19:09

Justin Herrera


The mongoose.model method accepts a type that defaults to mongoose.Document, which won't have properties you want on your User document.

To fix this, create an interface that describes your schema and extends mongoose.Document:

export interface UserDoc extends mongoose.Document {
  email: {
    type: string;
    unique: boolean;
    required: boolean;
  }
  ...
}

Then, pass that through as the type for your model:

export = mongoose.model<UserDoc>('User', userSchema);

like image 17
Nick Bernard Avatar answered Oct 23 '22 14:10

Nick Bernard


When I defined my entity interface I had it extending "Document" but had not imported anything.

When I crtl+click on it though I can see that it incorrectly thinks I was referring to the built-in node object "Document":

/** Any web page loaded in the browser and serves as an entry point into the web page's content, which is the DOM tree. */
interface Document extends Node, DocumentAndElementEventHandlers, DocumentOrShadowRoot, GlobalEventHandlers, NonElementParentNode, ParentNode, XPathEvaluatorBase {

After I explicitly told it to use Document from the mongoose library things worked. 👍

import { Document } from 'mongoose';
like image 1
Jim Avatar answered Oct 23 '22 14:10

Jim