How to write nice, typed and expressive node-express functions

In this post I’ll present a rather nice way of wrapping node-express controller methods in order to have a better self-describing codebase.

Let’s say you want to build an api endpoint that fetch some user, and returns it. Simple, yeah ?

1. A long time ago

A long time ago, people would write something that would read

Old school style, with callbacks and no typings. The legend says that people actually found this very cool for some time.

2. Nowadays

Let’s now go to 2017 and use typescript. First let’s take advantage of two features here:

  • typings
  • async/await

the code can be rewritten like this:

Note how await user.findOne(...) allows us to code as if our flow were synchronous. Besides, any exception (or rejected promise) will be caught by the main try/catch block. For more complex function, there is already a nice improvement. In case you don’t already know, I happen to be quite enthusiastic about async/await.

Also, try adding a typo, such as res.seeendStatus(500) and the typescript compiler will warn you about an unknown method. Because Result now has typings. Nice. Safe.

3. Even better ?!

I use the last example as a template for quite a while and it worked pretty well. Something would still bother me though.

By looking at this code, it is not obvious at first glance that this function returns a user. Adding some doc is an idea, but how can you be sure that the doc exactly describes what’s coded below (common answer: you don’t, thus you read the code anyways) ?

Of course this example is simple enough so you can read the method in no time. But why should you read a method when we are using typed functions everywhere ?

What we came up with at Hunteed is a wrapper that will allow us to declare the output of our express functions.

Before we dive into the details, here’s an example of what our final function should look like:

Here you can notice that:

  • We use some magical apiMethod decorator to reduce boilerplate.
  • First line tells it all : this wrappedShowUser function pretends that it returns an object that contains either a user of type User , or nothing at all.
  • We don’t write no try/catch (there should still be a try catch somewhere, but we are not required to write it every single time, at the risk of forgetting it )
  • The function actually returns the data we pretend to send. And typescript can check that we do. Yay !

Now for the implementation:


As promised, our final api method now reads

I really think this is some readable and self-describing piece of code. It takes advantages of typings, error handling, and guarantee that no-one will ever forget to use try/catch on an express api endpoint. Neat !

These people have absolutely no idea of what’s going on here, but they definitely look very happy about it.

More by Aurélien Hervé

Topics of interest

More Related Stories