Hooks 11 exercises

Typing State and Actions for useReducer

In this exercise, we'll be exploring useReducer and how to type a reducer function using TypeScript.

The useReducer hook takes in a reducer function, which accepts two arguments of state and action. The purpose of a reducer is to return a new state based on the provided action.type.


Loading exercise


0:00 For this exercise, we're going to be looking at useReducer. UseReducer takes in a reducer function, and that function takes in two arguments. We have a state property, or parameter, and an action parameter.

0:14 What happens is a reducer is just a function that takes in those things and returns a new state. Based on the action.type, it's going to do different things.

0:24 This action.type, we've got either add, which goes count, state.count + action.add, so action.add is probably going to be a number, in that case. Another action.type we've got is subtract. In the subtract case we - the action.subtract. These are the amounts that are being passed along with the action.

0:46 This should be working...It probably shouldn't be working, actually, because of these unknowns that we've added in, but at least some inference should be passed in because we're passing in an initial state into here, and we've got our state count equals any here.

1:01 Then we've got our tests. Our test is expecting state.count to be number, but it's being typed as any, and we've got a bunch of different cases for actions we should be able to send to this reducer.

1:12 The first one here, type add, add 1, that's all fine, and we expect it to be fine. We should be getting some autocomplete here, but we're not.

1:21 Then these ones should all be erroring, but they're not currently. This one should be erroring because it's uppercase, not lowercase, this one because we've omitted the add, and this one should be erroring because we're passing a string instead of a number.

1:34 Your job is to figure out how to type this function in order to make this work. There are three different solutions here, but mostly they're just about reorganizing the types. You'll probably find one of the solutions most appealing to you.

1:47 You will need to know about discriminated unions, and I've got a link to an article that I wrote on Total TypeScript about disco unions and their power. I think that's all the information you need. Good luck.