TypeScript Express Error Function

I don't know why Typescript does not get that we are passing an error handler.

These are the solutions I found possible :

app.use((err, req, res, next) => {}) // KO    

const inVariable : ErrorRequestHandler = (err, req, res, next) => {};

app.use(inVariable); // ok
app.use(((err, req, res, next) => {}) as ErrorRequestHandler); // ok

Custom Error Type

Using any completely gives up the type checking advantage of the Typescript. Because in JavaScript, one can throw anything, for err parameter, the type unknown can be used from Typescript 3.0 onwards:

app.use((err: unknown, req: Request, res: Response, next: NextFunction) => { })

Example

Create a custom error, if you need it, like following:

// HttpException.ts in exceptions directory of your project.

export class HttpException extends Error {
  public status: number
  public message: string
  constructor(status: number, message: string) {
    super(message)
    this.status = status
    this.message = message
  }
}

And then import the custom error wherever you are using it:

import { HttpException } from './exceptions/HttpException'

app.use((req: Request, res: Response, next: NextFunction) => {
    const err = new HttpException(404, 'Not Found')
    // Do something with error here...
    next(err)
})

app.use((err: unknown, req: Request, res: Response, next: NextFunction) => {
    if (err instanceof HttpException) {
        // Do something more with the error here...
    }
    next(err)
})

Because the type of err is unknown, we cannot directly access or modify the err. First we need to check the type using instanceof which as a result, smart casts the err to that type (HttpException in our case).

We can add any properties and methods to the HttpException class as and when required, like we have added status and message.


Type Definitions

In case you haven't done already, you need to install type definitions for Node.js and Express.js for your Typescript project. This will make sure the types Request, Response and NextFunction will be recognised and auto-imported.

To install type definitions for Node.js:

npm install --save-dev @types/node

To install type definitions for Express.js:

npm install --save-dev @types/express

That's it! Hope that helps.


The function itself has the following signature (taken from DefinitelyTyped):

export type ErrorRequestHandler = (err: any, req: Request, res: Response, next: NextFunction) => any;

So you can either declare the function as a variable of type ErrorRequestHandler or type the parameters according to that definition.

Note: the typings for "express-serve-static-core" are imported and re-exported by the typings for "express", which was where I looked for the above definition.

import type { ErrorRequestHandler } from "express";
const errorHandler: ErrorRequestHandler = (err, req, res, next) => {};

app.use(errorHandler);

Regarding your second question related to implicit any, it is the "implicit" part that is causing the problem, If you explicitly type as any then there won't be any error (but there won't be any typings either; consider using unknown instead).

You can also disable noImplicitAny in your compiler config but I wouldn't recommend it personally, as it protects you from several classes of bugs.