Error: The function findUser is not declared on the Model data type in Typescript/Mongoose

I'm currently working on a project that involves implementing authentication using MongoDB, mongoose, and express with typescript. However, I've encountered an issue with typescript while trying to declare the type for findUser in my model.ts file. Any suggestions on how to resolve this?

model.ts

import mongoose, { Schema, Document } from 'mongoose';
import bcrypt from 'bcrypt';

export interface IUser extends Document {
  username: string;
  password: string;
}

const userSchema: Schema = new Schema({
  username: {
    type: String,
    unique: true,
    required: true,
  },
  password: {
    type: String,
    required: true,
  },
});

// tslint:disable-next-line: only-arrow-functions
userSchema.statics.findUser = async function (username, password) {
  const user = await User.findOne({ username });
  if (!user) {
    return;
  }

  const isMatch = await bcrypt.compare(password, user.password);
  if (!isMatch) {
    return;
  }
  return user;
};

userSchema.pre<IUser>('save', async function (next) {
  const user = this;
  if (user.isModified('password')) {
    user.password = await bcrypt.hash(user.password, 8);
  }
  next();
});

const User = mongoose.model<IUser & Document>('User', userSchema);
export default User;

auth.ts (route) ERROR:Property 'findUser' does not exist on type 'Model<IUser & Document>'.ts(2339)

import express from 'express';
import User from '../models/user-model';
const router = express.Router();

declare module 'express-session' {
  // tslint:disable-next-line: interface-name
  export interface SessionData {
    user: { [key: string]: any };
  }
}

router.post('/signin', async (req, res) => {
  const { email, password } = req.body;
  const user = await User.findUser(email, password);
  if (user) {
    req.session.user = user._id;
    res.json({
      message: 'You are successfully login',
      auth: true,
    });
  } else {
    res.json({
      message: 'Unable to login',
      auth: false,
    });
  }
});



export = router;

Answer №1

To specify the model itself, you can set a second generic on the mongoose.model() method.

This includes all properties of Model<IUser> and allows for the addition of custom functions.

type UserModel = Model<IUser> & {
    findUser: (username: string, password: string) => Promise<IUser | undefined>;
}

The type for the documents in this model is determined by IUser, while the type for the model itself is determined by UserModel.

const User = mongoose.model<IUser, UserModel>('User', userSchema);

Once defined, the method's type is known. In this case, user will have the type IUser | undefined.

const user = await User.findUser('joe', 'abcd');

Visit the Typescript Playground Link to learn more.

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

What is the best way to transfer an object to a component through Angular routing?

In my "home" component, I have an array called mangas containing a list of objects that I iterate through like this: <div *ngFor="let manga of mangas"> <h1> {{ manga.title }} </h1> <button routerLink="/manga/{{ man ...

Serializing data in Next.js with MongoDB integration

Having trouble loading data from mongodb into nextjs and encountering a persistent error. The data has been added to the database using Python pymongo. SerializableError: Error serializing .jobs[0] returned from getServerSideProps in "/". Reaso ...

Expression in MongoDB $expr syntax

Within my collection, I need to filter data by comparing two fields with a modification on one of them. Currently, I am utilizing $where for this filter. The fields in question are lastTime and Threshold. This is how the $where filter currently looks: thi ...

What could be causing the rendering issue on this React component page when an id is provided in the React Router URL?

These are the dependencies I am using for my React project: "react": "^16.13.1", "react-dom": "^16.13.1", "react-helmet": "^6.1.0", "react-html-parser": "^2.0.2", "react-i ...

Express-validator is programmed to avoid identifying any duplicate entries within the database

While using Express-Validator to validate fields in forms on the frontend, I encountered an issue with the exists() function not working as expected. I have two forms - a register form and another form where Express Validator is used. The validation works ...

Is there an issue with validation when using looped radio buttons with default values in data-driven forms?

Within my reactive form, I am iterating over some data and attempting to pre-set default values for radio buttons. While the default values are being successfully set, the validation is not functioning as expected. <fieldset *ngIf="question.radioB ...

When selecting the "Open Link in New Tab" option in Chrome, the Angular app's routing will automatically redirect to the login page

I am facing a peculiar issue in my Angular 2 application that I need help troubleshooting. Currently, the routing within my app functions as intended when I click on links to navigate between different components. Here is an example of how the routing path ...

Establish a connection between Python and MongoDB

I've been attempting to establish a connection to MongoDB using Python with the following code: myclient = pymongo.MongoClient("mongodb://root:password@mongo:27017/database_sample?authSource=admin") db = myclient.database_sample my_collectio ...

Utilize API within an array to enable Ionic to display a PDF in a document viewer

Recently diving into the world of Angular and Ionic, I've come across some interesting API data: [{"ID":"1","Title":"Maritime Safety","File_Name":"9c714531945ee24345f60e2105776e23.pdf","Created":"2018-11-07 17:36:55","Modified":"2018-11-07 17:36:55"} ...

Nodemailer configurations with Mailtrap (Issue: Exceeding email rate limit)

How can I properly set up nodemailer options for the mailtrap free version? I keep encountering this error consistently despite my attempts: "Error: Data command failed: 550 5.7.0 Requested action not taken: too many emails per second" Note: Mailtrap fre ...

What steps can be taken to fix the SequelizeDatabaseError NaN error while working with sequelize?

I am encountering an issue when running a basic sequelize.js query for my model that's causing this error. Executing (default): CREATE TABLE IF NOT EXISTS `Books` (`id` INTEGER PRIMARY KEY, `title` VARCHAR(255), `author` VARCHAR(255), `genre` VARCHAR ...

What is the best approach to perform type checking on a function that yields varying types depending on the values of its

Currently, I am facing a challenge with a function that takes an argument and returns a different type of value depending on the argument's value. For instance: function foo(arg: 'a' | 'b') { if (arg === 'a') { ret ...

Secure User Authentication with NodeJs and MySQL Using Password Hashing

Trying to login with this information has not been successful so far. I am unsure of how to resolve this issue. During the registration process, I was able to successfully input a hashed password. However, when I attempted to log in with an incorrect pass ...

Utilizing a nested query for filtering in MongoDB $lookup

Exploring the functionality of mongoDB's $lookup feature, specifically utilizing the pipeline syntax to enable more intricate queries compared to the ORM I currently use (Sails/Waterline). A condensed snapshot of my data appears as follows.... / ...

The execution time of Node's Promises.all() function is unreasonably slow

I need to add a table containing data on sent emails after each email has been successfully sent. Within a loop, I am populating an array to be resolved using the Promise.all(). insertData is a function that adds data, requiring two parameters: connector, ...

Incorporate a fresh element into an object after its initial creation

Hello, I am looking to create an object in JavaScript that includes an array-object field called "Cities." Within each city entry, there should be information such as the city's name, ID, key, and a District array object containing town data for that ...

Handling the onSelect Event in React Bootstrap Dropdown using TypeScript

Using a combination of React, TypeScript, and react-bootstrap, I have created a dropdown list: ipc_handleSelect = (eventKey: any, event: any) => { } render() { return ( <Dropdown> <Dropdown.Toggle>Text</Dropdown. ...

Performing various tasks within one POST request in a RESTful API

Can multiple operations be handled within a single POST request? app.post('/api/bus_routes',function(req,res){ Route.find({ $and:[{path:req.body.p1},{path:req.body.p2}] },function(err,bus_routes){ //....... }); }); ...

MUI DataGrid Identifying Duplicate Rows

I'm encountering an issue with my Data Grid component from MUI when fetching data using axios. The console shows the correct data, but on the page, it only displays one result or duplicates. I suspect there might be a frontend problem, but I'm s ...

Attempting to invoke a TypeScript firebase function

I'm currently working on incorporating Firebase functions in my index.ts file: import * as functions from "firebase-functions"; export const helloWorld = functions.https.onRequest((request, response) => { functions.logger.info(" ...