---
title: "Typed Redux"
description: "One of the most popular examples on using Flowtype with Redux is the F8 app, open-sourced by Meta. Check the article for more details."
url: https://www.callstack.com/blog/typed-redux
updated: 2026-10-24T08:39:38.539Z
---

# Typed Redux

One of the most popular examples on using Flowtype with Redux is the F8 app, open-sourced by Meta. Check the article for more details.

_By Mike Grabowski, CEO & Founder @ Callstack · Published 2016-11-07 · Category: Developer Experience_

One of the most popular examples on using **Flowtype** with Redux is the F8 app, open-sourced by Meta last year.

It deeply integrates with **Flow**, most notably:

- It [replaces constants](https://github.com/fbsamples/f8app/blob/master/js/actions/types.js) in favor of a single union type _Action_ that describes the type and payload of every action that can be dispatched,
- [Later in reducers](https://github.com/fbsamples/f8app/blob/master/js/reducers/friendsSchedules.js), typed _Action_ helps developers to reason about the purpose of action and what could be done with its payload,
- Each branch of the state has a [corresponding type](https://github.com/fbsamples/f8app/blob/master/js/reducers/friendsSchedules.js#L29-L35) that helps with transforming it.

I have been using similar approach in most of my apps recently. However, I quickly noticed that some of these do not scale well as the app grows, especially when there are several developers working on the app. The setup I want to share with you today is a result of the tweaks and improvements that we added over time to the original _F8 App_ approach. I hope you’ll find it useful!

### #1 — Keep types in a single file

Our codebases tend to grow quickly as we add new reducers, actions and selectors. Having types spread across multiple files makes it harder to see them all at a glance and import to your components. It also creates a lot of cross references between files when you need to build a type that composes others inside.

In most of our apps, we tend to keep all the types in a single file. Usually we call it _types.js_ and place it in the root folder. Types that it contains are just named exports, like below:

[GitHub Gist](https://gist.github.com/callstack-bot/950bdd2bc532044f1a89e38a9a19413c)

[GitHub Gist](https://gist.github.com/callstack-bot/ecdcd4e811d01bbbbf119991ebe883b5)

that can be later imported in a very easy way:

[GitHub Gist](https://gist.github.com/callstack-bot/f44b7b6526746e034a5778bc3d7c3857)

### #2 — Describe your state

Although we promote keeping reducers small and atomic, they still contain the logic necessary to change the app state in a response to an action. Things get tricky when we fetch details from the API. We need to describe initial state and the lack of value as the request is pending.

Take the following example of two reducers’ state:

[GitHub Gist](https://gist.github.com/callstack-bot/6afbc38748119f71ee487c1681fb1f35)

[GitHub Gist](https://gist.github.com/callstack-bot/436fd5bd407ad98d78b50db712b1f440)

[GitHub Gist](https://gist.github.com/callstack-bot/5ae6628ced8c95bed95998ee7710abdd)

It has flow types for the _friends.js_ and _app.js_ reducers. All good — now we can use them inside our reducers like below:

[GitHub Gist](https://gist.github.com/callstack-bot/79a845c60ff9de29148c15478de0d6ad)

Did you actually notice that the above code has a type error?

[GitHub Gist](https://gist.github.com/callstack-bot/d2ab9864f8ab5a5db12bd3fd8cf21a21)

We declared that the _friends.list_ in state will always be an array, either empty or containing some fetched details. However, in our _initialState_, it’s default value is _null_. That would potentially cause an exception, since it changes the contract that was settled at the beginning.

Thanks to Flow and the state having a corresponding type, we were able to catch that tiny mistake as early as it happened. It’s these trivial mistakes that can potentially turn our app into an inconsistent or broken state. That’s why it is important to describe the state controlled by a reducer, so that you can catch these things as early as possible.

### #3 — Connect like a pro

When working with Redux, we use connect to map state to props of our containers and let them react to changes when they happen.

A simple example could be:

[GitHub Gist](https://gist.github.com/callstack-bot/49804c75b3477838b9e22bd15f755028)

How many times writing something similar you had to step back, check reducers and see the state shape? I guess a lot.

Now, since each of our reducers has its own type, like _FriendsState_ as we saw in the previous paragraph, we can easily introduce yet another one, called _State_:

[GitHub Gist](https://gist.github.com/callstack-bot/33f6726b415bd94aa25309be8c459b8d)

and use it in our connect:

[GitHub Gist](https://gist.github.com/callstack-bot/1565a14b63acb6f94793d37e493ce816)

This pattern helps us to reason about the entire app state as well as eliminate common issues, like misspelling the property names. Thanks to that, we can catch them early, as we type, instead of debugging it during runtime.

### #4 — Be careful with typing actions

Following the _F8 app_ approach, we describe our actions as a single, union type, called _Action_:

[GitHub Gist](https://gist.github.com/callstack-bot/3c6f6835798da5079f423a9896f3ed33)

However, union type holding information about all the actions, in the form as above, was something that stopped working for us as the app grew.

The main problem was that we were using _redux-promise-middleware_ to automatically dispatch success and failure case as the promise was either resolved or rejected.

What we really wanted is to have each action, especially the one that’s a result of an API call, to be fully typed, so that it’s easier to map response body of an HTTP request to the state. At the same time, we didn’t want to repeat things like _key_ and _payload_ every time, since effectively the only thing that’s changing is the response body itself.

So, instead of focusing on typing actions, we decided to create one generic type, called _ApiAction_:

[GitHub Gist](https://gist.github.com/callstack-bot/41a3def54cf4038a858341d51b40c101)

that can be used inside reducers to map an action with the payload.

Thanks to that, we could focus on typing payloads instead, as in this example:

[GitHub Gist](https://gist.github.com/callstack-bot/b5e5b221af1190a452bb45288f8cbcea)

Note: We already have a _Friend_ and _Friends_ type that we are using inside _FriendsState_, so it’s less typing for the same security.

Finally, implementing it in our reducer is as simple as this:

[GitHub Gist](https://gist.github.com/callstack-bot/e76758fdc42d517a9a98748077f283c4)

In this example, we define handlers as an object where each key is a type of an action to handle and function is a transform to be applied to the state. It can be described with the following Flow type:

[GitHub Gist](https://gist.github.com/callstack-bot/4e04da3f64eaec84b71669d5b5b72851)

If you are interested in an implementation of _createReducer_, check this [gist](https://gist.github.com/grabbou/16484dfb1aa9f787bb2d0b8f7dd08d29)!

### #5 — Use constants or not

Last important concept are constants. I haven’t payed too much attention to them just yet, mainly because they are not the main bottleneck inside the app, as it grows.

The focus we had was always on ensuring that it’s as easy for the developer to work with the action payload inside reducer rather than checking whether the action key is correct.

Having said so, up to this point, we tend to define constants in a separate file **the old school way**, however sometimes we define an enum, called _ActionType_ that can be used in all the above types we mentioned as a replacement to _string_:

[GitHub Gist](https://gist.github.com/callstack-bot/85841c18e84925971fc8edbf761e9809)

Flow will warn us in case of a spelling mistake.

## Wrapping up

There’s definitely a lot of fun when it comes to typing Redux with Flow. The amount of possible solutions, especially with actions, constants and reducers opens up a room for a lot of discussion and improvements. As always in this case, pick the solution that works for you and gives you the most benefits in that very project you are working. I hope the tips that I shared today will give you yet another point of view on using Flow with Redux!

Thanks to [Max Stoiber](https://medium.com/u/908fb8fea30c) and [Nader Dabit](https://medium.com/u/695782484bda) for making sure it can be understood by more than just me.

Discover services offered by our [React Native development company.](https://www.callstack.com/react-native-development-company)
