Creating custom validation functions with Mongoose

I've been involved in a TypeScript project that utilizes MongoDB for data persistence. Eliminating the use of any is one of our main objectives.

Here's an excerpt of code that defines a part of the mongoose schema:

priceMax: {
  max: 10000000,
  min: 0,
  required: function (this: FeePricing & Document) {
    return this.priceMin === undefined;
  },
  type: Number,
  validate: [
    {
      message: 'Max price cannot be lower than min price',
      validator: function (v: number) {
        if (this.priceMax === null || this.priceMax === undefined) return true;
        return this.priceMin ? v >= this.priceMin : v >= 0;
      },
    },
    {
      message: 'Max price cannot be higher than 50000 for this feeType',
      validator: function (v: number) {
        return !(feeTypesWithoutMaxLimit.includes(this.feeType) && v > 50000);
      },
    },
  ],
},
priceMin: {
  max: 10000000,
  min: 0,
  required: function () {
    return this.priceMax === undefined;
  },
  type: Number,
  validate: {
    message: 'priceMin cannot be higher than priceMax',
    validator: function (v: number) {
      return this.priceMax ? v <= this.priceMax : v >= 0;
    },
  },
},
updatedAt: { type: Date },
updatedBy: { type: String },

I have a decent understanding of what the functions are designed to do, but the usage of types within them confuses me.

How can I eliminate the need for this as any? Wouldn't it make sense to just utilize FeePricing as the type - like (this as FeePricing)? Is FeePricing essentially another type specific to my app [, with both priceMin and priceMax] combined with a Document interface? How does ReactJS's Document factor into this situation? Why is it necessary? Is this within validate referencing the previously defined type FeePricing & Document?

Appreciate your insights

Answer №1

this is where your validation setup comes into play. Since TypeScript struggles to determine the type on its own (due to potential changes), I suggest creating a custom type such as FeePricing. Without knowing the exact properties within your current FeePricing, here's a basic structure:

interface FeePricing {
  priceMin?: mongoose.Schema.Types.Number | null,
  priceMax?: mongoose.Schema.Types.Number | null,
  feeType?: mongoose.Schema.Types.Number | null,
}

You can then implement it like this:

(this as FeePricing).priceMax

The optional and nullable properties are intentional, considering that your logic involves checking for undefined or null. By defining them this way, you ensure accurate validation based on their potential non-existence during runtime. Feel free to rename the type if needed.

In regards to your query about ReactJs Document, it doesn't contribute to inferring the mongoose configuration type and can be omitted altogether.

Answer №2

From my understanding, Mongoose utilizes schemas to define the structure of documents stored in MongoDB. If I am correct, one can create a model/interface for FeePricing and use that as the data type.

export interface FeePricing {
  priceMax: number;
  priceMin: number;
}

this refers to the FreePricing object.

I hope this explanation is helpful.

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

Conflict arises in the path of merging (Angular)

Hi there, Encountering a merge conflict on the path "/src/app/employee.service.ts". while executing the following command ng generate service employee --skipTests=true I am using Ubuntu 20.04 as my operating system and have spent an hour sear ...

Change databases or collections in MongoDB instantaneously using a specified name

For my application, only read access is required for all databases. One particular database (db_1) houses a collection coll_1 that needs to be completely replaced at regular intervals. The goal is to minimize any negative impact on the read performance of ...

Is there a more efficient method for querying multiple fields in $geoNear instead of relying on $or?

I currently have a list of events and I'm looking to perform a search on both the title and description fields for a specific phrase in order to retrieve events within a given radius that match the search query. While my implementation using the $or ...

The ultimate guide to retrieving virtual attributes in Node.JS using Mongoose and MongoDB

Imagine I have a Mongoose schema set up as shown below: var Schema_MySchema = new mongoose.Schema({ Field1: String, Field2: String }); I have added a virtual attribute and set options in this manner: Schema_MySchema.virtual('USERNAME').get(f ...

Populate Dialog Form with Parent Data in React using Typescript

Incorporating Reactjs and Typescript, I am facing an issue with a parent component that retrieves data from an API and then uses it to trigger the opening of a Material-UI Dialog containing an editable form. The problem lies in prepopulating the dialog wit ...

Updating MongoDB - Synchronize following recovery of primary node from crash

As a newcomer to mongoDB, I have been exploring tutorials and came across a scenario that has piqued my curiosity. Let's consider a setup with 3 replica nodes: A, B, and C. Node A is currently the primary node, syncing data to the other two nodes eve ...

Is it possible to incorporate a counter into a MongoDB query?

I am looking to enhance my query results by adding a counter to each matching document. For example, I'd like the first document to have a counter value of 1, the second document to have a counter value of 2, and so on. Below is a snippet of the data ...

Having trouble with filtering an array using the some() method of another array?

When utilizing the code below, my goal is to filter the first array by checking if the item's id exists in the second array. However, I am encountering an issue where the result is coming back empty. dialogRef.afterClosed().subscribe((airlines: Airli ...

What could be the reason for my inability to import styles.css from @rainbow-me/rainbowkit?

Currently, I am in the process of integrating the rainbowkit and wagmi libraries into an existing website that is built using web3. The integration works fine when I comment out the styles import, but unfortunately, it results in a rather unattractive appe ...

Managing variables that have not been assigned in Typescript

An error is encountered during compilation when running the following Typescript code: ts(2454): Variable "timeout" is used before it has been assigned, specifically in the catch statement. let timeout: NodeJS.Timeout try { prepareConnection(() => ...

Does the state remain unchanged when assigning an Angular service?

I am trying to grasp the inner workings of Angular. I have a standalone component called TestComponent that receives TestService as an injection. This component invokes the method this.testService.assign(). Later, a Guard injects the TestService and calls ...

Unexpected token @ while using Angular2 with jspm and gulp for typescript compilation

Recently, I've delved into learning about Angular 2 and its accompanying technologies. In an attempt to create minified and "compiled" versions of my .ts files, I started using gulp-jspm-build. However, I encountered an error that has left me stumped. ...

What are the advantages of utilizing multiple databases for handling distinct collections in MongoDB?

For instance, let's say you have a blogging platform built with MongoDB for data storage. Would it be more beneficial to create a separate database for each blogger, considering their blogs and comments are completely isolated from other bloggers? Or ...

Angular: "An unexpected token was encountered. Please supply a constructor, method, accessor, or property as expected."

It's quite puzzling why I encounter a compile error when I use the var or let keywords to declare a variable. Interestingly, this block of code runs smoothly: export class AppComponent { refreshClickStream$: any; constructor(){ } Howev ...

Run mongoose queries sequentially and return the first successful result

StopsModel.findOne({stop_lat: stations[0]}).exec() .then(function(stop){ if (stop) res.json(stop); else { StopsModel.findOne({stop_lat: stations[1]}).exec() .then(function(stop){ if (stop) res.json(stop); els ...

Discover how to generate nested dynamic routes in NextJS by linking to MongoDB data using the getStaticProps and getStaticPaths functions

Currently, I am facing a challenge with implementing dynamic paths in NextJS and I'm struggling to find a solution. Let me provide some context for better understanding. I am working on developing an ecommerce application using NextJS, and the folder ...

Add the $or operator to your MongoDB query

I'm currently using mongoose to run the following query on node. Contacts.find().where("_id", id).where("types", "presenter").exec(function(err, doc){ Now, I want to add another value, Presenter, to the second where clause. I attempted the followin ...

Using TypeScript to call a class method from within another function

Currently, I am working on an Angular 2 application and struggling to grasp the concept of TypeScript's this scope. Within my TypeScript class named SharedService, there is a function called handleError. If this function encounters a 401 status, I wa ...

Expanding a div with CSS and Angular: A comprehensive guide

For my project, I am working on a specific scenario: When the user clicks on the "Animals" tile, it should expand while the other tiles replace it. Similarly, clicking on the "Plants" tile should expand it and reorder the other tiles. ===========1st View ...

It is essential for the object to contain a method called '[Symbol.iterator]()' which will yield an iterator upon invocation

Currently, I am facing the following error: error TS2488: Type 'Usuario' must have a '[Symbol.iterator]()' method that returns an iterator. This is my code: usuarios.reducers.ts export interface UsuarioState { users: Usuario[]; ...