11
votes

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?

3
Isn't user.generateJwt(); function asynchronous? - chridam
It isn't. I just truncated it from brevity. Also, the line saving user never logs which leads me to think that is isn't getting far enough for generateJwt to be the problem - xerotolerant
@xerotolerant How did you solve this? - lonix
I’m not sure. I’ve been using typescript and mongoose a bit since then but I used typegoose in my most recent projects - xerotolerant

3 Answers

12
votes

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);

-1
votes

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';
-4
votes

If anybody is looking for a solution to this like I was, I had the exact same issue and realized you needed to add a type to var user.

It should be var user: any = new User();.