Lesson Description
The "Typing Reducer Actions" Lesson is part of the full, React and TypeScript, v3 course featured in this preview video. Here's what you'd learn in this lesson:
Steve discusses reducers and discriminated unions, discussing the current state of the counter reducer and the need to eliminate the use of 'any' in actions. He demonstrates how to refactor the counter reducer and integrate it into a user reducer, explaining the importance of defining the shape of actions to avoid runtime errors and advocating for the use of 'unknown' for stricter type checking.
Transcript from the "Typing Reducer Actions" Lesson
[00:00:00]
>> Steve Kinney: With that, we're going to segue into reducers and this idea of what's called a discriminated union. We have this reducer in the same project here called counter reducer, and like, it's a little bit naive right now, where it takes some kind of initial state. At this point, we have like the initial state object set up in this case, and an action, which is any, and our goal in life is to like get rid of all of these anys.
[00:00:31]
But we're not done today. So we have not achieved our goal just yet, and we will continue marching towards it. What is cool again with the counter reducer is that it has figured out the nature of, like, at least to the best of its ability, has figured out at least what state should be. It says or undefined because it doesn't, it has a default in there. And then like it kind of figured out the state that comes out the other end, and has that as well.
[00:01:06]
And so if we were to use useReducer, we would get some of that for free. And so we can even go export this, and we'll bring it into our counter from before. And now here we'll say, we'll go to this count here. We'll say const and we'll say count and dispatch is what comes out of a useReducer. UseReducer, which again, at this point takes some function that has the previous state and an action, and returns something.
[00:01:45]
So we'll go ahead and we'll pull in the, what do I call it, counter reducer. Again, the nice part is, if you forget the order of the arguments, right, you can see that you just hover over and see what the intelligence of the producers, the first argument, so on and so forth. So we'll pull in the counter reducer. And we need to pull in useReducer from React. Maybe. No, I got it. So I checked the squiggly line, it probably wants the initial value, expected 2 to 3 arguments, but got 1.
[00:02:24]
So I need to pull in that initial argument as well. Right. And now it kind of knows roughly what count is based on that function, and we're not using dispatch yet, so it's angry about that, but that's, it'll live. But like our counter reducer still does have some problems to it, right? Which is again, we said the action can be literally anything. So then, if we go ahead and we look at the action, not only is the action any, it'll let us call dot type on it.
[00:02:59]
Now if that happens to be a Boolean or something that doesn't have dot type on it, that's a runtime error. Like the second anything is any, everything it touches becomes any, right? So that's even why like draft count at the very end becomes like, here's the number, it came out as any on the other side. But we can like make this a little bit better by following some patterns. And so before we talk about all that, we can perseverate all the ways that any is broken and this reducer is problematic, or we can make this a little bit nicer.
[00:03:41]
So, the kind of first thing that we might seek to do is give the shape of our action some kind of shape, right? Like, cause an action doesn't necessarily need to be an object, but there is this thing called Flux Standard Actions, which is if you've used Redux, it's just a convention. If you've ever seen the thing where a type that has a string and then a payload that has some data, that is in like theory error or meta or something like that.
[00:04:18]
So we could say something like type action is a type of a string, payload. I would be tempted to do this, and I will for a second. We pop this in here. And now, at the very least, it knows that type is a string and that action is some kind of, in this case, action object. The payload, for instance, like, what is the type with increment, decrement and reset, I guess, like set to would be a different one, like it doesn't know what that is, and so this is still infected with being any.
[00:04:53]
And you're like, sometimes like, I don't know what it is yet, leave me alone. In that case, what you actually want, anytime you think you want any, and somebody on your team tells you that they had to make it any for reasons, I would argue that what you really need is unknown. Right, cause any is just like, I don't know, do whatever you want. Unknown is literally like, you need to check it first, right?
[00:05:17]
Like you're not allowed to really do anything with it until you've done some kind of runtime validation of what it is. So like, unknown could be anything, but until you figure out what it is, you can't really do much with it, right? Now, if you said, if typeof, you know, typeof payload equals equals equals string, inside that conditional block, guess what that value becomes. A string. If you say, you know, typeof whatever equals equals number, it's now a number.
[00:05:55]
If instanceof some class, and you're inside that block, guess what it is, right? Also, if you say like, hey, it could be a string or number and you say if string returns something, for the rest of the function, TypeScript will know that it's a number, because it would have returned if it was a string, right? Or if it's not a string, throw an error. Then for the rest of the function, it will know that it's a string.
[00:06:18]
So you have to do some checking. But like you don't get this kind of like wild west where it could be literally anything, call whatever properties you want on it, so on and so forth. So like anytime you think you need any, and you're about to do one of these little fun things that is only acceptable because like, it's a workshop and we're refactoring stuff, you almost definitely want unknown. Right, and then you can figure out what it is later, and I will show you some fun tricks for that.
Learn Straight from the Experts Who Shape the Modern Web
- 250+In-depth Courses
- Industry Leading Experts
- 24Learning Paths
- Live Interactive Workshops