Explainer: Type Helpers in Redux
Let's take the work we've done on Type Helpers and put it into context by taking a look at the source code for Redux.
The reducer types inside of src/types/reducers.ts show us many of the same techniques we've been working with.
For example, here is the
0:00 Let's take this work that we've done on TypeHelpers and put it in context. We're inside the Redux open source projects. We have Redux here inside the package.json. I'm inside the reducers file here. This is inside source/types/reducers.
0:15 Now, this file is really interesting because inside here, we basically express a lot about what we want the types in the Redux library to look like. One of them is this reducer type.
0:28 If you never heard of what a reducer is before, there's a wonderful explanation here. A reducer also called reducing function. You can see what it is supposed to look like from this type definition here.
0:40 We've seen a lot of these pieces before. We have a type of reducer here. We have two generics, one called S, another one called A. We can look at what a reducer is supposed to look like by using it here.
0:54 Let's say, we've got a reducer and you can see that both of these have defaults. I don't need to pass anything to this reducer. I can just create a function here.
1:04 Let's say we've got state and actions, since those are our two elements here. We're going to return state, since we actually return this S here. We've got a perfectly valid reducer.
1:16 Now, a reducer can basically have two different parts associated with it, states and actions. A state here, we can actually add this to our first parameter, if we have the count number.
1:28 Now, the state is going to be represented as count number. If I just say, state.count++. In fact, it's going to be undefined. We need to give it a default of count is zero, and then I can remove this.
1:44 Now, we've got our reducer, we've got state and our action. Now, we need to understand what action is all about. What it looks like, A extends Action equals AnyAction.
1:56 There are a couple of other types here that we've built in. We've got an action thing there and this is from the actions.ts file. We've got reducers right next to actions.
2:07 What it looks like it's saying is an action is any objects with a type. It has to have a type attribute. That means that if I pass something to this, if I say, type MyReducerAction =, let's say, type: 'MY_ACTION,' then I'm going to pass this into the second parameter here.
2:26 This means now, the action is going to be typed as MyReducerAction. If I don't provide a type here, then this is going to yell at me, because property type is missing in reducer action, but required in ActionAny.
2:37 If I don't pass this at all, then I'm going to end up with AnyAction as my second parameter there, because that's the default.
2:45 It looks like AnyAction allows for extra properties that would be defined in an action, but it's pretty loose this type really. It extends action up here, but it allows any extra properties to be defined.
2:57 You do want to type this. Let's say we add that back in, MyReducerAction and type: 'MY_ACTION'. You can also add a second type here. This is a discriminated union. 'MY_OTHER_ACTION,' this is how you're supposed to type this.
3:13 Now, you have your reducer all figured out like this. You have your actions that can come in, you can say, if action.type equals 'MY_ACTION"). Then do this and this drives a lot of the behavior that's inside Redux.
3:27 Usually, you're not using the types like this. You're taking reducer, if we come and click in, I'm going to say, find all references here. What this does then is it looks for all the references throughout all of the files.
3:42 We're going to look inside. Let's say combineReducers. CombineReducers, if we look inside here, there we go. This is a very complicated looking function, because it's got lots of function overloads, which we'll learn about in a different section.
3:57 If you look here, then what we're taking in, we have a combineReducers function. It's saying, "OK, we have a ReducersMapObjects and we have a Reducer that comes out at the end of it."
4:09 CombinedState, it looks like it comes from another types area here. You can see how all of these type helpers really help you express the different language that your library is written in.
4:23 It gives you the ability to say, "OK, this is the shape of a reducer. This is the shape of a state." In any open source library, you're going to be using TypeHelpers, which rely on other TypeHelpers to express the reusable shapes and language that live in your library. This is a really great example.
4:40 There are tons of these for Redux. I would go and explore this particular file inside actions too. There are a bunch of these inside store and inside middleware.ts. You can really get a good sense for what Redux is trying to do just from looking at its types and its TypeHelpers.