Refactoring from Generics to a Discriminated Union
Looking at ModalProps
, we're trying to say that there are two different states for it to be in:
If you pass in the with-button
variant, you must also pass in buttonLabel
and onButtonClick
.
If you pass in the without-button
variant, you don't need to pass those in.
This is a classic use
Transcript
00:00 So what are we trying to do here with modal props? What we're trying to do is we're trying to say that there are two different states for our modal props to be in. Either you pass a variant of with button and you need to pass in button label on button click, or there's without button and you don't need to pass those in.
00:18 We've heard this before. This is a classic use case for a discriminated union. So let's refactor this to be a discriminated union. We can add, let's say, variant up there with button. Let me just remove some of this cruft around here.
00:37 We can say that we always need to receive is open. Let's add some parentheses here and just do that. Now we've got our with button variants working. Let me add those parentheses back and we end up with another union inside there.
00:54 Let's go variant again and now without button. So we can actually delete our possible variants here because they're now being grabbed from modal props. We can see that we actually don't need this T variant at the top here. To T variants, it's declared, but its value is never read, so we can simply remove it.
01:13 Now, T variant extends possible variants. I don't even need this. Well, we certainly don't need to pass in T variant into here because modal props is no longer generic. So let's do that. Now, T variant is not being used, so we can remove that one too. So now modal is just props, modal props, and we still get exactly the same behavior down the bottom.
01:32 So if I change this to without button, now this is going to error and it's going to error. So this lesson is really just a lesson in saying, you don't need to always use really fancy generic logic in order to get something done. We can actually do a lot just with focusing on this stuff here,
01:52 by doing work with discriminated unions. We're also going to look at function overloads in a future section, although they're less useful with components. But just to say that generics are not always the answer, and sometimes you can just get a cleaner output and make your code easier to understand by doing this stuff instead.