Unions and Narrowing 28 exercises

Limitations of Destructuring Discriminated Unions

Discriminated unions in TypeScript have certain limitations when it comes to destructuring.

When we trying passing in a Shape into a function before its specific type is known, TypeScript is only able to confirm the kind property. This is because the kind discriminator is common to all branc

Loading solution


00:00 OK, so the weakness of discriminated unions really is that you can't really destructure with them. You can in certain ways, but certainly not in this way. The reason you can't do this is because if you think about it, the moment that this is passed in, the shape is passed in, we don't know if it has a radius or a side length yet.

00:19 So technically TypeScript could get around this and say, OK, side length is undefined here maybe. But really what TypeScript just wants to do is give you the kind property, because that's the only one that's in common between them. So this rather confusing error, property side length does

00:35 not exist on type shape, what it's really saying is property side length does not exist on all branches of the type shape. So if we remove those and if we say, OK, what we'll do is inside this, let's say we get the shape back through our sort of a rest parameter in destructuring,

00:54 then inside our first branch of kind equals circle, we can say, let's just destructure again, and we can say const equals shape, const radius equals shape here. But now this is a little bit

01:10 annoying because kind inside the function parameter has been separated from the rest of the shape. It's no longer a property of shape, it's actually just been pulled out. And so TypeScript can't quite track the relationship between kind and shape. Oh, no. And so the destructuring here,

01:29 properties radius does not exist on type radius number or side length number. So it can't quite tell the difference. So the best way to do this, I think, is just to give up destructuring inside the actual body of the function, inside the function parameter, change that back to shape.

01:46 And we say if shape.kind equals circle, then inside this branch, we can now say const radius is shape. And now everything works because what we've done is we've said, OK, the narrowing is applied to a property of shape. That means that shape is properly narrowed down

02:05 to be a circle, as we can see from the hover. And that means we can, inside our function body, we can pull out radius. It means you don't have to kind of like grab something like from function property or object property. And we can do the same thing down below with the other branch.

02:20 And we can say const side length equals shape. And now everything just works. So this, I think, is the easiest way to do it, is to apply your destructurings closer to where they're actually used or do what I do, which is not actually destructure that much when you're using

02:38 discriminated unions. And in fact, I find myself not destructuring very often, certainly destructuring objects very often at all. I tend to just prefer actually just grabbing the properties and just sort of put them on. I don't mind lots of dots in my code. That's absolutely fine. TypeScript

02:53 lets you autocomplete. It's all really nice. But if you want to destructure, this is the best way to go.