Typescript Index Signatures, keyof Assertions & the Record Utility Type

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments
Captions
[Music] hello and welcome I'm Dave today we'll learn about typescript index signatures the key of keyword and the record utility type I'll provide links to example source code and all resources in the description below I've also recently started a Discord server and I've provided a link for you to join in the description below it's a great place to post any questions you have about this video and to chat with other web development students too we're starting today with a main.ts file that is empty so if you have code from the last lesson you can just select that all with control a and press backspace to delete it after that let's go ahead and open up a terminal with control in the back tick and if you already have typescript started you'll want control C to stop that because I'm going to start it right here with TSC and then Dash W for the watch flag and this will take any of the code that we have in our main TS file and compile a main JS file inside of our build directory over here and then we have an index.html and of course our code will compile inside of our JS folder we set all of that up way back in the first lesson so if you are starting here for any reason go back to the beginning and follow this course through in order okay I'm going to close the terminal window let's quickly go to the index.html file and I've got the vs code live server extension I'm going to click go live to go ahead and start the project so we'll be able to look at it in the browser and what we really want to do is look at the console I'll close the index and I will drag vs code over here to the left and then press Ctrl B to hide the file tree so we have more room for our code on the right I will select the browser and then press Ctrl shift in the letter i to open up Dev tools and I've got the console open here if I reload that live reload message goes away from our live server extension and now we're ready to write some code So today we're talking about index signatures and I can just comment that here at the top and index signatures are useful when you're creating an object but you don't know the exact names of the object keys but you do know the shape of the object and you can declare the type of the keys and the types of the values but there's another reason that they're also useful and that's because typescript requires an index signature if you attempt to access an object property dynamically and honestly that second reason is how beginners usually discover the need for index signatures I'm just going to paste in a basic interface here and you can see I've named it transaction object and I've got a pizza property books and job over here and all of these types are numbers this is how we've learned to create an interface that we would create objects from so now let me do that and I'll just say today's transactions and we'll make this a transaction object and then we'll go ahead and set that equal to an object that has a pizza and we'll put that at -10 we'll have books let's put that at -5 and then let's have a job and we'll put that at plus 50. and you can see typescript is fine with that we've provided all the required properties that we have inside of the interface but there could come a time where we wouldn't know what these names would be when we're going to create an interface in advance and that's where an index signature can come in handy but it can also be when we try to access any of those properties dynamically and so I'll show you what I mean by dynamically if we just try to access pizza from our today's transactions use dot notation and that's fine that's how we would of course find something or access that property I guess I'll save and we should see that over here in the console yes but let me go ahead and copy that down with control I'm sorry shift alt and the down arrow and we could also do that with bracket notation and I could say yes I want the pizza property once again I want that value and I'll save and I get -10 over here in the console again but let me show you an example of dynamically accessing this and this happens more often when we'd create a loop but first I'll do it without a loop I'll say let prop and now we'll say this is going to be a string let's just set it equal to the pizza string just like we used here inside of our second console log example so now prop is equal to Pizza so now I'll say console.log one more time and I'll say today's transactions use a bracket again and I'll pass in our prop this is how we would access it dynamically but look typescript does not like this and this is the error that beginners often see it says element implicitly has an any type and it says because expression of type string can't be used to index type and then of course it gives our interface and then it says no index signature with parameter of type string was found that's because we haven't created an index signature and we're trying to access this dynamically and I'm going to scroll up just a little bit and show you how this can apply to a loop as well so I just paste it in an example here and this is a function so I called it today's net and I'm taking all of the values here inside of our today's transaction because we're passing in a transaction object as transactions this function should return a number over here and you can see I start off with a total equal to zero I'm going to return the total but in the middle here I Loop through the object that is passed in the transaction object and normally in the four in Loop that I'm using here here's four here's in I've got transaction in transactions I'm accessing each one of those transactions and then just totaling them up however this is what we would do in vanilla JavaScript but in typescript we once again get that same error that we saw above when we tried to dynamically access this value so let's fix this by providing an index signature let's look at how we can do that first of all let's say we didn't know what any of these names were going to be so I'm just going to comment this out and then after we comment that out we'll just create another interface with that same name I'll say interface this is transaction object now inside the syntax looks almost like we're creating a property but it starts with brackets and then we can say index or you may see examples that use the word key Either would work and after that we'll say all of the keys in this object of the key value pairs are going to be strings and after that we can say all of the values are going to be numbers and now this is an index signature and it just declares that we know all of the keys will be strings and all of the values will be numbers and yes we could use Union types over here so we could say string and of course go on to say Boolean or have an array or any of those things the keys however are usually strings but they can be other things as well but it cannot be Boolean for example so I'll put Boolean in here and you can see typescript says I don't like that let me get rid of the other intellisense here we go it says an index signature parameter type must be a string number or some symbol or a template literal type so there are options but Boolean is definitely not one of those so I'll just put string back here now typescript should be good with everything we had below yes you can see we can now access this dynamically and our function today's net is also going to work as we Loop through the object inside of the function here so when I save this we should see all of those results over here so yes we accessed Pizza dynamically through the prop variable and that's where we get the third minus 10 and our function today's net that I call below it when we pass in today's transactions is a total of 35 and we can see that because we have 50 here and minus 10 and minus 5 when we passed in today's transactions let's also note that we could make this read only and that would not allow any assignments to any property inside of the object that is created so I'll save that and now let's go below and try try to assign something here so I'll say today's transactions and then I'll just use dot notation to get pizza let's try to assign 40. you can see typescript does not like that says index signature type only permits reading so we can comment that out but I'll leave it in the course resources inside of our source code here so you can access this and just see the difference Also let's look at one other example that could be a drawback because typescript can't see into the future it doesn't know what property names you're going to have either and that leaves something open that is not quite as safe so we could say today's transactions there we go press Tab and now let's try to access a property Named Dave and you can see typescript doesn't give us an error this is going to return undefined because it doesn't exist on the object but typescript has no problem with it because it has no way to know what names we would give the keys because remember our interface up here just says it's going to be an index of string and it should return a number so typescript really thinks this is going to return a number but it's going to be undefined as we see over here in the console so it's not entirely safe this does open up the possibility for you to try to access a key on an object that does not exist and so one more consideration what if we knew we were going to have pizza books and job in our object but we also wanted to provide an index signature and of course we could possibly add more well let's just copy this first we'll copy the index signature I'll comment out this transaction object at the top and let me bring this one back and at first typescript will have an issue and then it won't when we add in the index signature right here so this provides an index signature and this would allow other properties to be added to an object that was created with this interface however this interface will also require Pizza books and jobs you can see if I come here and cut job out typescript instantly gives us the red squiggly under today's transaction it says property job is missing but I could add something else underneath like Dave and just say hey but it doesn't like that because we said everything needs to be a number right so if I Mouse over this it says string is not assignable to numbers so maybe I should say 42 and now it's fine but Dave is not required the other three are because we have that in our interface let's scroll down and I'll provide another example below these so here we'll scroll and give a little bit of a comment line to divide our examples I'm going to create another interface call this interface student and then inside of this we'll have a name that would be a string and they'll put a comma after that let's also have a GPA and we'll call this number and finally Let's Do classes let's make this optional if you remember how to make it optional we start with a question mark first and let's have this be an array of numbers so now we have our student interface and by the way while I'm thinking of it we can use commas here semicolons and I believe you won't have an error even if you remove the comma or semicolon however stay consistent in whatever your choice is okay now we've got our interface and now after that I'm just going to create an object and I'll paste that object in you can see I'm creating a student object all lowercase from the student interface and so we've got Doug here with a GPA of 3.5 and he's in two classes the 100 level and the 200 level so right now this is a strict interface so if I said console Dot blog and tried to access student.test which doesn't exist you can see typescript says that's no good test doesn't exist on type student that we have above but what if we provide an index signature so once again I'll put this in and I'll say key string now over here we've got several different types so if I just say string typescript is still not going to like GPA or classes we have to put in every value type so we have number type script is still not happy with classes so we put in an array of numbers and let's look typescript is still not happy with classes why it says property classes of type number could also be undefined and that's because this is optional here so we also need to provide undefined when one of the properties is optional now notice a byproduct of providing this index signature on our interface student is typescript no longer has an issue with us trying to access test because now typescript doesn't know maybe it will have test so it goes ahead and lets us do this where before when we didn't have this index signature typescript said hey this doesn't exist on student so again just the potential for a problem there if we try to access a property that doesn't exist okay after that let's go ahead and write some more code that will iterate through our student here in a loop and will once again see what issue may occur so let's say four const and we'll say key in student now inside the loop let's access this and I'll use a template literal and here I'll say or well not four just the key itself so we'll log the key have a colon and after that we will log the student and now normally here we would just use the key and right now there is no problem with that so if we save we see name Doug GPA 3.5 classes 100 and 200 but if I come up here and comment out our index signature then we'll probably have a problem down here yes we're going to see that same issue right here so what I want to show is how you can iterate through an object you've created that does not have an index signature provided as we have here so I'm going to leave this commented out and now we're going to use the key of keyword and an assertion so when we access this and we can do this right inside the brackets we could say key as and now you know we're going to use an assertion say as key of and now we'll say student we'll list the interface and now notice typescript has no problem even though we don't have a key up here what key of does is creates a union type and the union type is the specific string literal so it's a union type of name GPA and classes that Kiev is creating and it allows us to still Loop through the object and you can see we get the same result here in the console I want to give one more example just an alternate version of this and I'll say object dot keys and I'll pass in the students well now you know this makes an array of the keys in the student object I'm going to map over those keys and then inside the function I'm going to log and I'll just log the student object but now we'll access this with brackets again so once again dynamically accessing the property values and I want to say key as key of as we did before but now imagine that we don't know what the student object what the type of it is so the interface we just have an object and we don't know exactly the type so now we could say type of and list the object itself notice it's the lowercase student not the uppercase student interface that we referenced here and now typescript is good with that too because now we're saying we don't know what the type of is so we're just retrieving the type of by referencing the object itself and this also works so when I save we'll see the difference in the console because I didn't use the same log of a template literal so we just accessed those values we got Doug 3.5 and our array that has 100 and 200 and now let's look at one more key of example and I'm going to do that with a function so I'll say const log student key this is going to be a function that has a student object passed into it and it's going to be the type of student that we defined in the interface and then we'll specify the key right here and in the parameters of the object we can just say key of student so we're defining what we're going to use as the key inside the function right here as we pass in the parameter and then I'm just going to say a void return so I guess I need to put that here and then have our Arrow then inside the function I'll just say console log and now we can put a template literal and I'll say student and now I'll say key and after that I'll put a colon and now we'll say student and with bracket notation we can access the key and notice there's no problem doing this and this is what we're used to from JavaScript already because we've clearly defined key up here as the key of student so once again it defines this key as a string literal and it's made up of the different names that are inside of students so name GPA and class is right there so once we save we should see this well I need to call the function first I guess we defined it here so let's say log student and now we can pass in our student object once I spell it correctly and let's get the GPA property and that's the one we're going to access so now we can see student GPA is 3.5 we could change this to one of the other properties that we had so we had name or classes let's go with name so now we should have student name is Doug so our function is working properly and typescript is happy with it I'm going to scroll up to the top so we have a little more room put in one more divider for our examples save that now I'm going to create an interface and I'll call this incomes and from what we learned before we can provide an index signature with a bracket there we go and I'll say keystring and then the values will be numbers and this is what we've essentially learned before and of course you could have different data types over here or Union and there are some other possibilities besides just a string over here we could even have a union of string and number if we wanted to and while typescript is good with all of that I want to show another way essentially the equivalent of providing this index signature here on the interface but we're going to do it with a type and I'll start by saying type and I'll call this streams and I'm just going to provide a string literal of you or a union type that has string literals I'll say salary after that we'll also have a bonus and after that let's also have well there we go I got the correct pipe now I'll say side hustle so there's our Union type for streams underneath that I'll Define another type and this type we'll call income so I'll need to comment out the one we have above because this is going to replace that and here we're going to use the utility type record now we use an angle bracket and I'm going to pass in the union that I created above so we could of course just copy this and paste it right in here to replace streams but it just makes it longer so it's easier to Define another type and then put everything in we want and put it right here and after streams I'm going to say these are numbers and close the angle bracket now that syntax is definitely smaller and it allows us to use string literals here as the different types that are expected and that comes into play when if I comment this out for example and come back to our interface up above and put this back in if I were to try to put a string literal in here and say salary you can see we instantly have a problem with typescript and it says it cannot be a literal type when we do it this way so if we want to provide a literal type here we can with the utility type record so go ahead and switch that back to what it had before which was string but then I'll also comment that out and we'll come back to our type here so this is a benefit now there could also be some issues because we're not specifically stating let's say we had another property up here like we did before I'll tab it over to look right but we had pizza and said this was a string for example and of course since I commented out it's given us a problem we can't do that here so if we had different property types say in our stream salary bonus and side hustle and we were accepting numbers and strings over here we're not saying salary is always a number and bonus is always a string when we do that we're saying salary can be a number or a string bonus can be a number or a string and the same for side hustle here we were able to declare specifically that pizza was always a string so a little bit of a drawback but also a little bit of a benefit where we can use these string literal types in as the keys so just below our record I'm going to paste in an object here and we'll call this monthly incomes and you can see it's based on our incomes that we have defined here the incomes type salary has 500 bonus has 100 and side hustle has two 50. now what if we want to Loop through these because I have said these were essentially equivalent so when we provided an index signature like we did in the interface up here we were able to Loop through things with no problem without an error can we still do that with the record utility type let's find out so I'll say four const let's call this Revenue in monthly incomes now inside the loop let's just log what we have so I'll say console log and I'll have monthly incomes and we want to use bracket notation and I put in revenue and look typescript has a problem with this unlike when we use the index signature inside of an interface or a type in this manner so now we need to of course use our assertion even though we have defined everything using the record utility type so here we would say as key of incomes and now everything is good once again in typescript so just know if you use the record utility type instead of providing an index signature like this you're still going to have to access key of so when I save we should now see 500 100 and 250 over here in the console remember to keep striving for Progress over Perfection and a little progress every day will go a very long way give this video a like if it's helped you and thank you for watching and subscribing you're helping my channel grow have a great day and let's write more code together very soon
Info
Channel: Dave Gray
Views: 14,585
Rating: undefined out of 5
Keywords: typescript index signatures, typescript, typescript keyof, keyof, keyof assertions, index signatures, typescript record, record utility type, No index signature with a parameter type of type, Element implicitly has any type because expression of type an 'any' type, ts index signatures, ts keyof, keyof keyword, looping through typescript objects, how to loop through a typescript object, how to loop through an object in typescript, type script, javascript, ts, typescript tutorial, js
Id: 2eAqXLi8q70
Channel Id: undefined
Length: 24min 10sec (1450 seconds)
Published: Fri Nov 11 2022
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.