The Flow: Type Checking with Flow in React + Redux tutorial will teach you how to use Flow in a React + Redux environment. Since JavaScript itself is a dynamically typed language, you will end up with several bugs in your JavaScript career, which could have been prevented due type safety. In terms of using Flow for type safety, it only needs a simple setup to get the advantage of a more robust application. Moreover your feedback loop during development will improve, since you get the type safety in your terminal/IDE. Flow was introduced the first time at the Scale Conference in September 2014 .
First of all we have to install flow-bin in our project.
Next we have to create a flow configuration file.
We keep our configuration empty in the beginning and add a flow script to our package.json.
Now we can start our type checking already.
You may see an error, because at this time of writing the tutorial there could still be an issue after the setup. Please refer to the Troubleshoot chapter.
There are no errors yet, but Flow should check our types shouldnât it? Itâs up to you to setup type checking for each file. Basically Flow will only check files which have either a /* @flow */ or // @flow annotations.
Letâs begin by adding our first type checking in one of our constant files.
src/constants/actionTypes.js
Check again whether you have any errors now.
Still no errors, because we didnât specify a type yet.
When there would be an exported function in the file, we would have to specify the functions input and output from the beginning due to its module boundaries.
Letâs add our first type check. Flow comes with several built-in types .
When we run our script again, we will see an error, because ME_SET is a string.
The output will show you the error with an additional description.
You are still able to start the app with npm start and open it in a browser. Flow doesnât prevent you from starting your app.
Letâs fix the type error and add more type checks.
There should be no errors when you run the script again.
Letâs add some more type checking in our reducers. First only add the annotation.
src/reducers/track.js
As already noted, flow requires to specify the input and output of exported functions by only annotating the file. We need to specify our function input and output to prevent these errors.
The reducersâ input and output gets type checked now. We say that the incoming state and action are generic Object types and the returned newState of the reducer is an Object as well. You can see that we can clearly specify the input and the output of a function. It is even more powerful in an functional programming environment where you have pure functions. When you run the script again, there should be no errors anymore.
At the end we didnât win a lot here, because we still input two generic Objects and output one generic Object. We can use type aliases to define our state object more specific.
The initialState, which we already defined before, can be used in that case as blueprint for our type alias. Moreover we are using a maybe type , because activeTrack can be null. Neither we want to specify a null check within the reducer for the activeTrack, nor we want to prevent activeTrack from being null, because there doesnât need to be a set activeTrack in the first place.
There should be still no errors when you run the script again. We could even be more specific with the type Object here, by changing
but for the sake of simplicity, letâs leave the reducer as it is and be more specific in our next case.
So far we have type checked some of our actionTypes and one of our reducers. Letâs have a look at one of our action creators and make it type safe as well.
src/actions/track.js
A lot is happening here already! Letâs examine it from top to bottom. We define a type alias Track which has a property foo typed as string. After that we define two more complex type aliases. Both SetTracksAction and PlayTrackAction have a defined type as string. Moreover the first one has a property tracks which is typed as an Array of our type alias Track. The latter one has simply a property track types as type alias Track. Now we can use everything we defined in our action creators as input and output types.
Additionally you could also describe all actions under one type, but it doesnât guarantee you that you returned the correct object in the end.
The unified type is called a disjoint union type .
There should be no errors.
Letâs step in our file where we initially retrieve the track objects and make this one type safe.
Again we define a type alias for the track object. Moreover we define a more complex type alias StreamData which uses the Track type. It defines a property collection which is typed as an Array of Track types.
You should get an error now. If you look closer at the error, you will notice that it involves our action creators in track.js. Since we import the setTracks function from track.js, setTracks was already type checked before. When we have a look again at track.js, we will see that we defined the Track type alias different from the Track type alias in auth.js. One time it has a property foo typed as string and one time a property foo types as number. Now you see the power of the type safety which you will get with a static typed language. Flow is able to evaluate exported and imported modules .
We can easily fix that by changing our Track type.
You should see no errors anymore when you run the type checking script.
One problem from the previous step still remains. We had to define two times the Track type. It would be more useful to define the Track type only once. Moreover the Track object has no property foo in our real world application in the first place. We will have a look at the latter one later during this tutorial. Letâs fix the duplicate Track type definition first.
We can use declarations to define new types at one place and reuse them with Flow. Remember when we added the flow configuration? We can use that file to define the declarations.
Now we need a folder decls where we can decelerate our types at one place.
Now we can remove the
from the files src/actions/track.js and src/actions/auth.js. There should be no error when you run the type checking script.
Flow makes it possible to type check the props and state of nested components . React already comes with PropTypes, they are awesome and you should use them, but they can be improved with Flow. PropTypes for instance cannot specify the input and output of a function.
Letâs add the Flow annotation and the props objects we want to type check in the next step.
src/components/Stream/presenter.js
Since the prop object is an empty object, we will get several errors when we check our types. We can adjust our props type check to justify the required props of our component.
That way we can exactly specify each property. Moreover you can see that we can define onPlay more specific. Rather than having a generic Function type, we can define the input and output of onPlay.
We still get errors and now comes the crucial point. In our auth.js we defined the StreamData which we will get from the SoundCloud API ( Whatâs an API? ). At this point we have no chance to know about the property types inside of Track. Since we are now defining the component where we want to make the tracks visible in the browser, we know which properties we need. Letâs change our Track declaration according to the properties we are showing in our Stream component.
We can even be more specific:
Now the Track declaration should align with the required props on our track object in the Stream component.
As little extra we can declare a User type, which we can use in the Stream component.
We have type checked one reducer, some action types, two action creators and one component. Moreover we declared globally Type aliases and made sure that our type checking runs across multiple files. Now you should be able to apply the type safety to the remaining files.
You may run into the issue that you canât start your app again with npm start nor test it with npm test. Please refer to the Troubleshoot chapter.
You may encounter issues in that tutorial. Here you will find some references how to handle issues.
You may run into an issue where it says
which happens in node_modules/fbjs/lib/. We can ignore that error in the flow configuration.
Now you should see no errors after running the type checking again.
After the type checking of the Stream component, you may run into a problem that your app doesnât start anymore with npm start nor the tests get executed with npm test. You may see the following error:
To fix that problem you can install the following package.
In case you want to know which versions npm installed during that tutorial, here a list of all npm packages in my package.json.