Pure Functions with Typescript

Oscar
3 min readJun 8, 2022

--

At the base of the functional programming paradigm lies the concept of pure functions. These types of functions allow developers to keep the application stateless by avoiding side effects and providing a predictable processing flow.

By the Wikipedia definition a pure function is:

In computer programming, a pure function is a function that has the following properties:

the function return values are identical for identical arguments (no variation with local static variables, non-local variables, mutable reference arguments or input streams), and

the function application has no side effects (no mutation of local static variables, non-local variables, mutable reference arguments or input/output streams).

Ok so now that we have an idea of what it means we can start with some examples.

A simple way to get our heads around the first pure function rule is by checking some of the functions that break the rule.

The first one is Math.random , this function breaks the rule because the return value will keep changing every time that it gets executed. Even if we get the same two values in a row, the implementation is meant to return an unknown number value.

Another good example is Date.now , which always returns the time between the 1st of January of 1970 to Now in milliseconds. No matter how many times you run it, you’ll never get the same result.

What’s a good example of a function that matches this rule then?

I don’t want to be like the lazy teacher that just says, (x, y) => x + y is a clear example, because… well how many times you’ll be writing a function like that, right?

Instead, we can do it by using React. An example would be a functional component that:

  1. Is not connected to any store.
  2. Doesn’t use any context hook.
  3. Doesn’t use any mutating static variable.

Something like:

These types of components are named presentational components or dumb components.

It doesn’t break the rule because every time that the same props are passed to the component it will always render the same information.

Now let’s talk about the second rule. To start, let’s imagine that we have a function to add a new item to a products basket that needs to update both the product array and the total price.

A way to write this would be to have an addProduct function that would receive both the basket and the product. Then, updating the basked with the latest product by pushing it to the productsarray and updating the totalPrice by summing up the product’s price.

This breaks the pure function rules as it is causing a side effect to the basket parameter by updating the productsand totalPriceattributes. By printing the result from this function we get:

Ok, so how can we convert it into a pure function? A way of doing that is by generating a new basket object within the addProduct function and returning that instead.

This way we are ensuring that the initial basket state is never changed and can be used later if there is a need to roll back or just to track the history. This is the result of the new implementation:

As we can see here the original basket object is not changed, instead, we have a separate instance with the updated values.

Why are pure functions important?

  1. Pure functions are easier to debug and test because for the same input they should always return the same output.
  2. By avoiding side effects you can get around race conditions and object pollution that can cause hard-to-trace bugs.
  3. Pure functions are the gateway to other functional programming practices like currying, high-order functions, and object composition.

This blog post is part of the Functional Programming with Typescript series on how to integrate functional programming principles for your application while keeping it type-safe with Typescript.

Introduction | Next >

--

--