Skip to main contentSkip to navigationSkip to navigation
Programming code abstract technology background of software developer and Computer script
Programming code abstract technology background of software developer and Computer script
Programming code abstract technology background of software developer and Computer script

Async Failure handling in Typescript

This article is more than 4 years old

We look at a pattern which makes dealing with failures in async functions easier to reason about

At the Guardian, we’ve been using Typescript to bring some of the type safety that we enjoy in Scala into the world of javascript. By shifting some of the work ensuring what we write is valid to our tools, we see a robust increase in our quality and productivity.

Since starting to use typescript, we’ve fairly dramatically increased our use of node backends. From our new website to our collection of node lambdas.

During the editions project, I built a little wrapper for Promises which was inspired by error handling patterns from both golang and scala.

In es6, when writing asynchronous code using the async/await syntax, errors from promises are thrown and must be caught using a try/catch block.

Allow content provided by a third party?

This article includes content hosted on gist.github.com. We ask for your permission before anything is loaded, as the provider may be using cookies and other technologies. To view this content, click 'Allow and continue'.

Consider a function which runs three async functions in serial:

Allow content provided by a third party?

This article includes content hosted on gist.github.com. We ask for your permission before anything is loaded, as the provider may be using cookies and other technologies. To view this content, click 'Allow and continue'.

Trying to catch each of these errors independently with try/catch can become messy.

Allow content provided by a third party?

This article includes content hosted on gist.github.com. We ask for your permission before anything is loaded, as the provider may be using cookies and other technologies. To view this content, click 'Allow and continue'.

One alternative to this is to declare the variable before the try block, and then change it. However, this isn’t a particularly good reason to perform a mutation and the error may end up improperly handled without it being obvious.

Allow content provided by a third party?

This article includes content hosted on gist.github.com. We ask for your permission before anything is loaded, as the provider may be using cookies and other technologies. To view this content, click 'Allow and continue'.


In both these slightly contrived examples, the flow control is somewhat difficult to unpick. And in the second, there is a chance of using B without it having a value.

In golang, functions communicate whether the have succeeded or failed by returning an error value alongside their results. Handling the value of this, handles the error encountered in the same manner as so-called ‘happy path’ code.

Allow content provided by a third party?

This article includes content hosted on gist.github.com. We ask for your permission before anything is loaded, as the provider may be using cookies and other technologies. To view this content, click 'Allow and continue'.

In Scala, a common error handling strategy is for a type to either be the successful result of the function- or the reason it failed. The type system is then able to reason about whether the function was successful or not, preventing you from using the value if there may have been an error.

Combining these ideas, you might get something like this:

Allow content provided by a third party?

This article includes content hosted on gist.github.com. We ask for your permission before anything is loaded, as the provider may be using cookies and other technologies. To view this content, click 'Allow and continue'.

Wrapping promises with the attempt function will catch any errors from the promise, and return either the output of the function or a value containing the thrown error.

This uncertainty is encoded in the type of the value returned, and a helper function is provided to check whether the function was successful.

Quick Guide

How do I join The Guardian Product & Engineering?

Show

Where can I find open positions?

Apply for one of our open positions here.

What can I expect from the interview process?

We aim to be as fair and transparent as possible in our hiring process. Similar to other organisations, there is a CV screening, coding exercise and a face to face interview. Read more about what to expect and apply now here, and read more about our department here.

Was this helpful?

Typescript is then able to reason about whether the error has been handled or not, allowing each error to be reasoned about neatly.

If this way of handling errors makes sense to you, we have published this as a library called ts-failure under the MIT license for you to use in your own projects.


Explore more on these topics

Most viewed

Most viewed