Allow Optional Props Using A Discriminated Union Branch With Undefined Types
In order to get our tests passing, we need to change the InputProps
type because it's not explicit enough about saying "don't include value
and onChange
in the branch".
Here's how the InputProps
currently look:
// Starting point
type InputProps = (
| {
value: string
Transcript
00:00 So in order to get this working, we need to change this type here. This is definitely a fender because it's not explicit enough about needing to say, don't include value and on change in this branch. Because this branch currently, because we're using this empty object type, which can sort
00:17 of receive any number of properties, it's too permissive at the moment. So we need to change this so that it's basically saying, don't include value and on change in this branch, and you're allowed to include both of them in this branch.
00:32 So the way we can do that is by specifying value again, and we're going to say undefined here. And on change too, we're also going to say undefined. So this means now instead of having this kind of like empty object type, which is going
00:48 to sort of permit you to do lots of weird stuff in it, we're actually saying this object here, it's always going to be undefined no matter what you pass in. So here now, on this first one, we're hitting the correct branch. So we're saying value and on change up here.
01:04 And then if I add value here, then it's going to warn me if I don't add on change here, which is super duper nice. So this setup is really, really cool because it lets you be much more explicit about different props that you're passing in.
01:21 A lot of people think that the correct solution to this is actually by passing never into here. And this does work. But this only works actually because never in this situation is actually reduced to undefined. So if I say const input props, and let's say it's going to be input props here. Beautiful.
01:40 And I just pass in label 123. Now if we look at input props dot on change, you can see here that it's actually not like it's not resolved to never, it's actually resolved to undefined. And that's because in this position, never actually reduces itself to undefined.
02:00 Because never actually, if you take a look at it, type example equals never or undefined. If never is in a union with something else, it will always just reduce itself out of that union.
02:14 So the proper best way to define this is actually as undefined, because that never even makes it into the type itself. So this is really, really nice. It's a little bit verbose. And I'm going to show you later in this module, how you can take this and turn it into a type
02:32 helper that you can reuse again and again and again.
02:35 But for now, understanding how this works is enough.