Maintain Intellisense in Express Handler Wrappers

Wrapping ExpressJS handler functions is a common practice. I especially like express handlers for catching errors in async functions and redirecting them to global Express error handling middleware.

The following is an example of such a handler:

When the passed async Request Handler fails with an exception or Promise rejection, the error will be passed to the next function and it will be sent to the first error handler in the middleware pipeline.

We can use it in our Express application like this:

This allows for centralized error handling and simple clean code with out intrusive try/catch blocks. But that’s a matter for another discussion.

The issue we face when wrapping Express request handlers is that we miss important typings for the two primary arguments, The Request and Response objects. Now unless you are still writing code in your green-text-in-black-background nano editor running on your custom build of Kali you probably take advantage of some form of auto-complete. Visual Studio Code for example offers Intellisense. Intellisense if the practice of the editor providing information for object members and function signatures to you dynamically while writing code.
Here’s a screenshot of Visual Studio code showing a list of members that can be found in the response object:

Intellisense was made with typed languages in mind so what can we do in JavaScript? (“Write TypeScript is a completely valid answer to this question and I endorse it”). Well in JavaScript, we need to work a bit more to maintain Intellisense and since we can’t just state that req is a request object and res is a response object when declaring the callback inside the wrapper we have to use code metadata and VSCode will understand.

With some simple modification in the wrapper module we can maintain Intellisense and save ourselves the headache.
First, we have to dig into Express typings. Typings are d.ts files that provide metadata for JavaScript modules. Not all libraries have them, but at least Express does. You can view Express’ typings by ctrl-clicking on a require statement that points to express:

Searching the file we can find the following:

Notice that we have to use ES6 module syntax when importing RequestHandler.

We need one last change to make this work. We need to open the async-wrapper.js file and convert our module to a named one:

Notice that we have to use ES6 module syntax when importing RequestHandler.

We need one last change to make this work. We need to open the async-wrapper.js file and convert our module to a named one:

Now if we check a file where we use AsyncWrapper, we can see that Intellisense is back.