Error in TypeScript when compiling Mongoose document middleware

Problem

After upgrading to TypeScript 3.4, I found that some of my Mongoose middleware functions were failing type checking.

Error Message from TypeScript:

model.ts:19:8 - error TS7017: Element implicitly has an 'any' type because type 'typeof globalThis' has no index signature.

19   this.modified = new Date();

Schema Definition:

Schema.pre("save", next => {
    this.modified = new Date();
    next();
});

Attempts Made to Resolve

Upon using TSLint, it recommended to first cast this to unknown and then cast it to the model type as a workaround.

Schema.pre("update", next => {
    (<Model>(<unknown>this)).modified = new Date();
    next();
});

Although this method seems to work, it is not the most elegant or intuitive solution.

Seeking Suggestions

I am looking for a cleaner way to tackle this issue without having to disable any TypeScript rules. Any suggestions?

Answer №1

Hey there, for the most effective solution, refer to this relevant git issue : https://github.com/Automattic/mongoose/issues/5046

The explanation provided in the issue is as follows:

The problem does not stem from Typescript. The issue lies in the usage of fat arrow syntax for defining mongoose methods and hooks. Avoid using fat arrow functions for defining pre-save hooks as they lack lexical scope and cannot be bound to a specific context.

To resolve this, simply replace next => with function(next) {}, and everything should function correctly.

Answer №2

Swapping out => with function(next) {} appeared to yield the correct value in this case. However, TypeScript raises an error if attempting to access this.username

Error: TS2339: Property 'username' does not exist on type 'Document'.

To resolve this issue, you have a couple of options. You can either utilize getters and setters such as this.get('username') and this.set('username', 'John'), or implement the following approach:

export interface IUser extends mongoose.Document {
  usernname: string,
  password: string
}

const usersSchema = new mongoose.Schema({
  username: String,
  password: String,
});

usersSchema.pre<IUser>("save", function(next) {
  const user = this;
  // Both user.password and user.username are accessible here.
  next();
});

const User = mongoose.model<IUser>("Users", usersSchema);

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

Require assistance in accurately assigning a date to a Date[] in Typescript Array without altering current elements

In my current code, I have a loop that verifies if a date is a holiday and then adds it to an array. The issue I'm facing is that whenever I assign a new element to the array, all previous data in the list gets updated to the latest element. Here&apos ...

The response code in the API remains 200 despite setting the status code to 204 in NestJS

I have developed an API that needs to return a 204 - No Content Response import { Controller, Get, Header, HttpStatus, Req, Res } from '@nestjs/common'; import { Response } from 'express'; @Get("mediation-get-api") @Head ...

Creating a record type with specific keys associated with values while leaving the rest undefined

Consider the scenario where the following code is implemented: const myObj = { "hello": "world"; } as const; const anyString: string = "Hi" if (myObj[anyString]) { // Element implicitly has an 'any' type because ...

Refresh Form Following Submission

When using a react form that triggers a graphql mutation upon button click, the text entered in the form fields remains even after the mutation has been executed. This necessitates manual deletion of text for subsequent mutations to be run. Is there a way ...

Efficiently loading Ionic 3 components within a tab with lazy-loading functionality

Need help with adding a new tab to your project using lazy-loading? You can utilize the @IonicPage decorator for setting up a page as the root of a tab. To implement this, create a new page: // module import { NgModule } from '@angular/core'; ...

How can you store form field validation rules (for example, firstname.dirty) in an array within TypeScript in Angular?

How do I save form field validation rules in an array? What should replace /'''''HERE'''''/ with? formfields: Array<Object> = [ {label: "Employer:", control: "employer", val ...

Enhancing your TypeScript version

Whenever I try to update my global version of TypeScript by running npm install -g typescript, the Angular project still shows an older version when I run ng v. Why does this happen and how can I ensure a consistent upgrade? https://i.stack.imgur.com/JzwK ...

Is the return type determined by the parameter type?

I need to create an interface that can handle different types of parameters from a third-party library, which will determine the return type. The return types could also be complex types or basic types like void or null. Here is a simple example demonstra ...

Create a MongoDB schema template for a fresh project setup, excluding any existing data

I currently have a nodejs project that utilizes a mongodb database. I am looking to create a new deployment of the project for a different client, but I want to maintain the same database structure without any existing data. How can I achieve this? Do I n ...

Protractor for Angular 2: Pausing execution until specified element obtains a specified class

Looking for a method to delay my e2e test (angular2 project) until the targeted element receives a specific css class. Is there an alternative approach without using browser.wait() or browser.sleep()? ...

Unleash the power of a module by exposing it to the global Window object using the dynamic

In my development process, I am utilizing webpack to bundle and manage my TypeScript modules. However, I am facing a challenge where I need certain modules or chunks to be accessible externally. Can anyone guide me on how to achieve this? Additional conte ...

What is the most effective method for merging two arrays in JavaScript?

Can a function be created to generate an array like the following? ["0-AA", "0-BB", "1-AA", "1-BB", "2-AA", "2-BB", "3-AA", "3-BB"] This particular function combines two array ...

The provided argument in Typescript does not match the required parameter type, which should be a string

Encountering a TypeScript error with the following code: if (this.$route?.query?.domainName) { this.setDomain(this.$route.query.domainName); } The code snippet above is causing the following error message: TypeScript - Argument of type 'string | ...

Timeout with Promise

I'm looking to enhance my understanding of working with promises by rewriting this function to resolve the promise instead of resorting to calling the callback function. export const connect = (callback: CallableFunction|void): void => { LOG.d ...

Perform an Angular HTTP request and await responses from multiple sources

I'm currently working with Angular 11 and looking to make an HTTP call to an API that will trigger a server-side process. Here's the code for the HTTP call: processData(data) { return this.httpClient.post('https://myurl/api/process&apos ...

cssclassName={ validatorState === RIGHT ? 'valid' : 'invalid' }

Is there a way to dynamically add different classes based on validation outcomes in React? My current implementation looks like this: className={ validatorState === RIGHT ? 'ok' : 'no' } However, I also need to handle cases where the ...

Is it possible to inject a descendant component's ancestor of the same type using

When working with Angular's dependency injection, it is possible to inject any ancestor component. For example: @Component({ ... }) export class MyComponent { constructor(_parent: AppComponent) {} } However, in my particular scenario, I am tryin ...

Iterating through a for loop in Angular2 to send multiple GET requests to a Django backend

Currently, I'm facing a challenge with performing multiple GET requests using Angular2 within a Django/Python environment. After successfully making an API request and retrieving a list of users to determine the current user's ID, I utilize a .f ...

TypeScript: Retrieve the data type of the provided object

Is there a way to create a function that receives a callback and returns the object returned by that callback? Here's an example of what I'm trying to achieve: const my_object = my_function<A extends string, B extends boolean> ("my_o ...

What are the steps to incorporate a 3D scene into a React website?

Can I get some advice on how to create a React web application using TypeScript? I want to be able to click a button and have it show a new page with a scene of a town. What is the best way to achieve this in my React project? I've heard about using R ...