Errors 10 exercises
solution

Working Around Type Conversion Errors

TypeScript gives us an error when trying to convert a cat into a Dog because there isn't sufficient overlap between the two types:

interface Dog {
	bark: boolean;
}

let cat = { purr: true };

let dog = cat as Dog; // red squiggly line under `cat as Dog`

This warning message is like

Loading solution

Transcript

00:00 Okay, let's break down the error work out why it's occurring conversion. What is being converted from one thing to another? Well, we're trying to convert a cat into a dog, right? We're trying to convert type per Boolean to the dog interface, right? And it may be a mistake. So it's basically sort of this is like a warning to you, essentially, because neither type sufficiently overlaps with the other.

00:27 So there's not enough overlap for TypeScript to say, sure, you've actually converted this properly. And so it's giving you a warning, right? It's basically saying, are you sure? Like, it's like, you know, you're trying to whack it over the head, because as the as assertion is kind of like a whack over the head to TypeScript, and it's sort of fallen to the ground and it's going, are you sure you meant to do this? I don't think you really meant to.

00:49 If this was intentional, convert the expression to unknown first, and then it gives you the actual reason for why it's happening. Property bark is missing in type per Boolean, but required in type dog. So we could, for instance, we could certainly say bark true here. And now the error would totally go away because we've added a bark property to the thing that we're trying to assign to it.

01:12 Can I do like a per like Boolean up here too? Yeah, now there's enough overlap between them because dog might contain a per. And so because basically TypeScript only shows this error, if you're trying to convert two objects which have no shared properties, so it's more like a convenience error.

01:34 And because it's a convenience error, it's saying, if this was intentional, convert the expression to unknown first. And so you can actually do this, you can say cat as unknown as dog. And this will often come up in in code because TypeScript has actually warned you to do this and told you to do it. But this is totally unsafe. What we're doing here is we're saying, okay, we're forcing it absolutely forcing it to be a dog here.

02:02 And so TypeScript sort of lets you do this. So this is equivalent to doing as any as dog. It's absolutely equivalent. Neither is better than the other here. You might get a warning about one from your linter, but not from the other.

02:17 So this is pretty dangerous, and you often shouldn't be doing it. But there might be situations where you want to do it, and you don't care about the consequences. Because the consequences are here that you could do something like, let's say, dog.bark.valueOf, for instance, and this would be a runtime error because bark doesn't actually exist at runtime.

02:40 So we are lying to TypeScript. TypeScript has tried to warn us not to lie to it by giving us this long error by basically saying, are you sure? Are you sure? Neither type sufficiently overlaps with the other. There's no overlap here. But sure, here's the way you can knock me out if you want to.

02:57 So this is what is causing this error. And this is a way around it. But this error really is a red flag saying you can probably find a better way of modelling this. So if you want to do this, I would actually prefer you to use as any as dog, because it's more explicit that this is something that you're doing that's wrong here. Morally wrong, you know, terrible.

03:19 So you should actually flag it as something that really shouldn't be done and something that should be refactored later. You can even add a comment here saying, find a better way to do this, please. Someone more senior than me, let's say. So yeah, this is what this error means. This is how to get around it. But I really do recommend you follow the error and try to find a different way of modelling this.