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

Written by aherve | Published 2017/05/15
Tech Story Tags: javascript | typescript | nodejs | expressjs | es6

TLDRvia the TL;DR App

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

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:

Conclusion

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.


Published by HackerNoon on 2017/05/15