Simplifying parameter types for error handling in app.use callback with Express.js and TypeScript

With some familiarity with TypeScript but a newcomer to Express.js, I aim to develop a generic error handler for my Express.js app built in TypeScript. The code snippet below is functional in JavaScript:

// catch 404 and forward to error handler
app.use((req, res, next) => {
  next(new createError[404]());
});

// error handler
app.use((err, req, res, next) => {
  // set locals, only providing error in development
  res.locals.message = err.message;
  res.locals.error = req.app.get('env') === 'development' ? err : {};

  // render the error page
  res.status(err.status || 500);
  res.render('error');
});

However, when attempting to compile this using TypeScript, an issue arises with the anonymous function in the second app.use call:

error TS7006: Parameter 'err' implicitly has an 'any' type.
app.use((err, req, res, next) => {
         ~~~

error TS7006: Parameter 'req' implicitly has an 'any' type.
app.use((err, req, res, next) => {
              ~~~

error TS7006: Parameter 'res' implicitly has an 'any' type.
app.use((err, req, res, next) => {
                   ~~~

error TS7006: Parameter 'next' implicitly has an 'any' type.
app.use((err, req, res, next) => {
                        ~~~~

Evidently, TypeScript managed to infer the parameter types for the first anonymous function in the first app.use call, but not for the second one.

By modifying the line as follows, TypeScript no longer throws any errors... although now eslint flags it for utilizing implicit anys:

app.use((err: any, req: any, res: any, next: any) => {

In another approach, Visual Studio Code offers a quick fix option "Infer parameter types from usage" for the second anonymous function. This results in the following format for the second app.use line (with added line breaks for clarity):

app.use((err: { message: any; status: any; },
         req: { app: { get: (arg0: string) => string; }; },
         res: { locals: { message: any; error: any; };
                status: (arg0: any) => void;
                render: (arg0: string) => void; },
         next: any) => {

While this may function appropriately, I find it rather unwieldy and difficult to comprehend.

Hence, the question arises: How can a similar implementation be achieved without sacrificing maintainability and comprehensibility?

Answer №1

The issue you are encountering originates from the configuration settings in your tsconfig.json file.

"noImplicitAny": true

It is recommended to use strict typing in TypeScript. Here is how I manage errors and specify types for each argument. Please install this package:

npm i -D @types/express
import { NextFunction, Request, Response } from 'express';
...
this.app.use((error: unknown, req: Request, res: Response, next: NextFunction): void => {
      if (error instanceof HttpException) {
        res.status(error.code).send({ message: error.message });
        return;
      }

      if (error instanceof Error && error.message) {
        if (error.message === 'Method not implemented') {
          res.status(501).send({ message: httpStatusCode(501) });
          return;
        }

        res.status(500).send({ message: error.message });
        return;
      }

      res.status(500).send({ message: httpStatusCode(500) });
      return;
    });

If you're curious about the HttpException class, here it is:

export class HttpException {
  constructor(public code: number, public message: string = httpStatusCode(code)) {}
}

By setting up this system along with an async handler for middleware, you can easily handle errors, including those from failed promises, all in one central location.

https://i.stack.imgur.com/x5f4S.png

https://i.stack.imgur.com/4Zell.png

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

Sending data in a POST request using Express

I'm currently attempting to send a POST request for a new user to Intercom using the request module, but I'm facing difficulties in getting the format right. Interestingly, I can successfully execute GET requests with request and even post data u ...

What method can a user of an Express app use to determine the location of the server?

I recently started learning about web development. Currently, I have set up an express server that serves a small static web application. The next step is to make the web app consume a RESTful API from the same server. However, I am unsure of how the clie ...

Angular: Issue encountered when accessing nested properties within an interface due to reading properties of undefined

Encountering difficulties with utilizing nested property interface. //Food Interface (food.interface.ts)// export interface Food { name: string; quantity?: string; description?: string; nutrients?: { calories?: number; protein?: number; carbs?: ...

How can serverless platforms handle binary data such as PDF files?

I am currently experiencing an issue that involves uploading a PDF file in Vue.js to a serverless Node.js application, resulting in broken file content. This problem occurs due to the serverless platform incorrectly parsing binary data types. How can I e ...

Does a typescript module augmentation get exported by default when included in a component library?

Utilizing material-ui and Typescript, I developed a component library. By implementing Typescript module augmentation, I extended the theme options as outlined in their documentation on theme customization with Typescript. // createPalette.d.ts/* eslint-di ...

Error Message: The Reference.update operation in Angular Firebase failed due to the presence of undefined value in the 'users.UID.email' property

Having recently started to use the Firebase database, I encountered an issue while trying to update the UID to the Realtime Database during signup. The error message displayed was: Error: Reference.update failed: First argument contains undefined in prop ...

Can default values be assigned to a DTO during initialization?

What is the method to assign default values when a query is empty? In the case where I have this DTO structure for a query: export class MyQuery { readonly myQueryItem: string; } If the request doesn't include any query, then myQuery.myQueryItem ...

Increasing the number of service providers in Angular2-4 directives

Is there a way to apply both * to a string? Below is the code snippet I am working with: <a class="sidenav-anchor" *ngIf="!item.hasSubItems()" md-list-item md-ripple [routerLink]="[item.route]" routerLinkActive="active" [routerLinkActiveOptions]="{ex ...

What is the optimal ranking system for learning in Mongodb using Node.js and Express? How can we best utilize these

1 - What is the recommended order for learning (Mongo db,Node.js,Express)? 2 - Is this platform compatible with both web and mobile devices? 3 - Can you explain the functionalities of the programs? 4 - I'm planning to integrate it into my Flutter m ...

Setting up Webpack for react-pdf in a Next.js application

In my Next.js application, I am utilizing the react-pdf library to generate and handle PDF files on the client side without involving the server. However, I am facing challenges in setting up Webpack for Next.js as I lack sufficient expertise in this area. ...

Tips for effectively handling errors in NodeJS

As I venture into the world of NodeJS and Express, I find myself faced with the challenge of asynchronously calling DB functions. This is quite different from my experience with other popular scripting languages and a C++ background. Despite figuring out a ...

Unable to write or upload error in a Node Express application

My GET and POST APIs are functioning properly, however, my app.put is not working as expected. Upon sending a PUT request to localhost:3001/contacts/1 using Postman, I am unable to see the console.log output: app.put('/api/contacts:id', (req, ...

ExpressJS - The execution of JavaScript in this framework does not strictly follow a top-down approach

Having issues with this particular script not running as expected, particularly in the variable reassignment section. Below is the code snippet and output: // Code to Create New Open Market in the game let latestRowId = 1; var sqlQu ...

I am encountering an issue where my React application is unable to establish a connection with my Express application when I dockerize them together. Can anyone

Currently tackling a project for my university that involves using a react app for frontend, an express app for backend, and mongodb as the database. Previously, I would launch the express app and react app separately before dockerizing them, and everythin ...

Error in Typescript: The 'type' property is not found in the 'string' type

I am working on creating a React component that includes subcomponents within it. I came across this insightful article that has been guiding me through the process. The concept is to design a Modal component with distinct sections such as Modal.Header, M ...

What is the best method for accessing a store in Next.js with Redux Toolkit?

Currently, I am working on incorporating integration testing for my application using Jest. To achieve this, I need to render components in order to interact with various queries. However, in order to render a component, it must be wrapped in a Provider to ...

Utilize the Multer file upload feature by integrating it into its own dedicated controller function

In my Express application, I decided to keep my routes.js file organized by creating a separate UploadController. Here's what it looks like: // UploadController.js const multer = require('multer') const storage = multer.diskStorage({ dest ...

Fullcalendar in Angular fails to update events automatically

I am exploring the integration of fullcalendar with angular. Despite adding valid events to my events field, they are not displaying in the UI. However, hardcoded events are appearing. I am relatively new to angular, so the issue may not be directly relat ...

Can one controller in a mean stack handle two models concurrently?

Exploring the world of MEAN STACK and tackling a project related to user entry and exit has presented me with an interesting challenge. Each user's username is stored in a separate collection, prompting me to consider creating 2 models within a single ...

Is it feasible to store the response outcome in a database using express-gateway?

Hi there, I have a question regarding express-gateway I configured routing in express gateway and when I tested it using Postman, I received the following response: { "response": { "rescode": "0", "hp": "0822xxxx", "vtype": "ADB", "server ...