Techniques for Solving Property Does Not Exist on Type Error
Understanding TypeScript Error
We encounter an error when trying to declare a new property that isn't predefined in our type or interface.
Property 'age' does not exist on type '{ name: string }'.
In this case, the age
is one dynamic part, and the { name: string }
are bot
Transcript
00:00 Okay, let's investigate this. This age property here, property age does not exist on type name string. We can see that there are two kind of like dynamic things going on here. So the age is the dynamic part of this error. And the other dynamic part is this name string object here. Where's this name string coming from? Well, if we hover over user here,
00:19 we can see that it's being inferred as name string. Now this is interesting because TypeScript only lets you index into properties that it knows exist. And what we're doing here when we say user dot something is we're indexing into it. So the only one that we can potentially index into
00:37 is user dot name here. And so we can either do it with a dot syntax or with user name here. So how do we tell this object up here that it might contain an age property? That's interesting. Well, that is solution one because what TypeScript is doing here is it's saying,
00:57 okay, you've added a name property to this, but I don't see anywhere that I'm supposed to care about an age property as well. So we can tell TypeScript that it's supposed to care about an age property on this user, even though it doesn't exist yet. We can declare a type of user and then say user is user
01:16 and then give it an optional age property. If we were to give it a non-optional age property, then we would have to declare it, property age is missing in type name string but required in type user, we'd have to add it when we actually create the user. But we now have to do it like this,
01:32 where we say const user, user dot age equals 24. We can even go super wide on this as well because what we're doing here is we're saying, okay, we have a type of user that has the keys of name and age associated with it. But we could say that this user is a record
01:50 and this record would be essentially an object with an index signature of string. So essentially you can just like index into any part of this object and then you can add onto that either a number or a string. So works with a number or a string, doesn't work with a Boolean, let's say.
02:09 Type Boolean is not assignable to type string or number. There you go, that's assignable again. So yeah, there's a couple of solutions here. And you might be looking at this original code and thinking why doesn't TypeScript just infer this for me? Why doesn't it just say, okay, yep, you want to dynamically add
02:29 like an object property here, that's totally fine by me. Well, TypeScript, like it has to make choices as to what kind of things it's going to error on and what kind of things it isn't going to error on. And what TypeScript has decided is that in general this kind of code,
02:46 it's more likely to be a bug than not. So if you don't know or TypeScript doesn't know about what shape this user is supposed to be, it's not going to try and infer it based on what you do, because this code could very easily just be refactored to just age 24, you know?
03:04 And now of course, like because TypeScript understands that there is an age property on there, it's actually going to let you kind of manipulate it and do stuff to it. And it knows that then user has an age property. So if you find yourself writing a lot of code like this, where you're constructing objects sort of later down the line, often it's actually just better to refactor it
03:23 into creating immutable objects or objects at least created like this instead of created dynamically. There are situations of course, where you want to create objects which are relatively dynamic. And in those situations you can use records. So records are really interesting and we're going to revisit them on a couple of exercises in this course, I think.
03:43 But in general, you will want to tell TypeScript about potential object properties that your object could contain. And then further down the line, you can add them. So yeah, this is what this error basically means. Property X does not exist on type Y. You either need to use TypeScript to tell TypeScript about it.
04:03 So you type annotations like this or widen out that type even more, or if you can just move the declaration in line and then you just get all the benefits of doing so. And you don't actually need to use any TypeScript to make this work.