TypeScript Basics Setup1:16
You also have this tsconfig.json file, which allows you to configure the behavior of the compiler and specify the flavor of JavaScript you want to compile down to. So, you'll see here that the target is ES5, and there's a bunch of other options here as well. Let's go ahead and start with some basics here. Let's work in our app.tsx. And let's just define some variables here. So, let's say let name equals Andre. Let's say let age equals 30. And let's say isCool equals false.
And same for the other variables as well. Old. We get a similar error. Now, if you want to have more than one type, say, for example, we wanted age to be a number or a string, we can use the pipe operator, I believe it's called a union type in TypeScript. So we can say union and a string as well. And now this should be valid. You can see it's string or number right here. Or you can specify the most generic type, which is type any in TypeScript. And that should work as well.
Typing Functions3:06
Or you can specify the most generic type, which is any in TypeScript. And that should work as well. Generally speaking, you don't want to do this because that defeats the whole purpose of using TypeScript. But just know that that's a type as well. Now, what about functions here? Let's take a look at one. Let's say greeting. Let's say it takes a param of name. And let's just return.
Let's say it takes a param of name. And let's just return. Hi, name. Okay. Let's save that. And we do have an error here. Let's see what it is. It says name has an implicit any type. So to get rid of that error, we can specify any here. But in this case, let's make it a string.
And this works for arrow functions as well if you prefer that syntax. So let's go ahead and define it using arrow syntax here. Let's just duplicate this. Let's say const greetingTwo equals. And we can put an arrow here. And that should be the same thing. So again, if we try to use this without the correct params, then it will throw an error. And same for the other one here. And like I said earlier, this is one of the main benefits of TypeScript.
Typing React State4:53
Let's say const age setAge equals useState. I'm going to hit Tab so it imports. And let's give it 30 as a default value. Now again, TypeScript is going to try to infer this type based on the param you provide here. And if you hover over age, you'll see that it's of type number. And also for setAge, it expects a parameter of type number. So again, if you're working with age and you don't provide a number in this case, then TypeScript will throw an error. So again, let's create a function here. updateAge.
So again, let's create a function here. updateAge. No params. And we can specify void here if you want to be explicit about the return type. But you don't have to because it is inferred correctly after we actually define the method body here. So in this case, we're going to do setAge. And setAge expects a number here. So if you don't provide a number, then TypeScript will throw an error. Now, if you want to be explicit about the type here,
Typing Objects with Interfaces6:12
And you can see the error is gone here. So say, for example, you accept null values. If we say null here, this will not work. But if you wanted to add that to the accepted types, you can put it here. And now it should work. Let's take a look at how we can handle objects here. So I'm going to paste in a to-do array. So I pasted in a to-do array. And it's an array of objects here. And each object has an ID, title, isComplete, and isEditing.
And it's an array of objects here. And each object has an ID, title, isComplete, and isEditing. Again, TypeScript's going to do its best to infer the type. So if we hover over to-dos, you'll see that the type is an array of this object type because it's looking at the default value and trying its best to infer the type. So in this case, it is correct. So again, if we try to use to-dos, either to-dos or set to-dos, and don't provide a to-dos array, then TypeScript will throw an error. So let's do the same thing we did here, but for to-dos.
and don't provide a to-dos array, then TypeScript will throw an error. So let's do the same thing we did here, but for to-dos. Update to-dos. And let's say set to-dos. And you can see null is not an accepted value here. So TypeScript throws an error. Now, what would happen if we didn't have this default value here? So let's just make it an empty array as default. So let's just remove this, save that. And let's hover over to-dos here.
So let's just remove this, save that. And let's hover over to-dos here. And you can see that type is never. So that means TypeScript could not infer the type correctly. So in cases like these, you want to define the structure of a to-do in this case. So to do that, we can use interfaces. So let's go ahead and define that up here. Let's say interface. Let's name it to-do.
Let's say interface. Let's name it ToDo. And what types do we want a ToDo object to have? So we want an id, which is a number. And for interfaces, the separator is a semicolon and not a comma. So make sure to take note of that. The title is a string. isComplete is a boolean. And isEditing is a boolean as well. isEditing boolean.
And is editing is a boolean as well. Is editing boolean. Now, if you want an optional field here, you can do that as well. So let's say we had an expires field here. We can say ? : And that's a number, but it is optional. Now, for our to-dos here, we can specify that it has this interface. So down here, we can use generics again to specify that. It is a to-do array. OK.
It is a to-dos array. OK. Now, if we hover over to-dos, you'll see that it is a to-dos array here. Let's go ahead and update this. Let's actually make it valid here. So I'm going to use the spread syntax to grab the to-dos. And let's append another to-do here. So let's say id 4, title, finish, video. Say isComplete, false. And isEditing is false.
Say is complete, false. And is editing is false. So you saw those red squigglies as I was typing. So those were showing up because this object wasn't conforming to that interface. So say, for example, I added foo bar here. You'll see that we have the red squiggly. And if we wanted to, we can also add that optional field, expires. And again, these yellow squigglies are for not using the function or the variable.
Typing Component Props9:32
And again, these yellow squigglies are for not using the function or the variable. But I'm not too worried about that right now. In the next video, we'll actually do a practical example. Let's take a look at props and other components. So I'm going to make a new component here. Let's use it in here. So after the P, I'll just make a toDoList component here. toDoList. And let's create it in here.
To-do list. And let's create it in here. So new file, to-do list.tsx. And let's make it a React functional component with an export. OK, that's fine for now. Let's go ahead and import this. OK, that should have imported it. Let's save this. And I do believe my server is running. So let's see if it runs in the browser.
And I do believe my server is running. So let's see if it runs in the browser. OK, so there's the to-do list. And I want to pass it in some props. So let's pass it in the toDos. Let's say toDos equals the toDos here. And you can see already that TypeScript is complaining because we didn't specify the props in that component. Let's also pass it a name here, and we'll just hard code that to my name.
Let's also pass it a name here, and we'll just hard code that to my name. OK, let's go ahead and accept these props in our component. So you would accept them in here as props. And the error here should be that any error. So for now, let's just say any to make it work. And you can also destructure it here if you like. So in this case, we have to-dos and name. And if we used the name, for example, in here, that should work.
And if we used the name, for example, in here, that should work. So let's just say div and name. That should export or output our name here. And it does. Let's go ahead and fix this any here to make it specific. So props is an object. And like I just showed you, you can use an interface to type objects. So let's do that.
you can use an interface to type objects. So let's do that. So let's say props here. Let's define a new interface right here called props. Or sometimes you'll see it named IProps for interface. Props is fine in this case. And what is it accepting? So in this case, we have two props. We have our to-dos, and we also have our name. So what type is to-dos?
We have our toDos, and we also have our name. So what type is toDos? So just like earlier in our app.tsx, in our state up here, toDos is of type ToDo[]. And for the ToDo, we define the interface up here. So we want to use this in that file as well. So we can either export it from here and then import it in that file, or we can move this to an external file. So let's just add this for now.
or we can move this to an external file. So let's just add this for now. It should be a to-do array. And the name is a string. And if you're using Prettier and you save, it should automatically add the semicolons here. Okay. So I'm gonna move this interface to its own file. So let's grab this. Let's make a new file here called interfaces.ts.
So let's grab this. Let's make a new file here called interfaces.ts. Let's paste that in. Let's go ahead and export this so we can import it from other files. So let's say export interface toDo. Okay. Let's use it in our app.tsx. So we can say import toDo from interfaces. Okay.
Let's save this and make sure it still runs in the browser. And it does, cool. Let me show you another way you can specify the prop types here using arrow functions and generics. So instead of the function keyword, we can use arrow functions. So let's say const todoList equals, and we can do the same thing here and we can destructure the props.
and we can do the same thing here and we can destructure the props. So toDos and name, and we can put an arrow here. But for our toDoList definition here, we can use generics again. Now this might look a bit confusing. Generics is more of an advanced topic in TypeScript. Actually, we're only using generics for the type here, but the toDoList should be of type React.FC
Actually, we're only using generics for the type here, but the to-do list should be of type React.FC for functional component. And then in the angle brackets, we can say it's of type props, which we just defined above. So these two are almost similar. At one point, I think this was the default, but if you take a look at this issue here, you'll see that it was removed.
And that should be valid. Let's double check our browser. It is. But like I said, it was removed, so I'll just stick to this other syntax here. So I'll just leave that in as a comment, but leave it as this syntax here. Another thing you can do is specify the return type for this entire function here. So if you hover over toDoList,
for this entire function here. So if you hover over toDoList, you'll see that it returns a JSX.Element. So you can actually put that as a return type here if you like. So JSX.Element, and that should work as well. Again, TypeScript infers it, so a lot of the times you won't see that, but I'll just leave it in here to be explicit. So we can do the same for our app.tsx,
Rendering Lists and Events14:46
but I'll just leave it in here to be explicit. So we can do the same for our app.tsx, for our function app. So there it is, jsx.element. Let's just put that in, and that should be fine as well. Okay, a few more things here. Let's take a look at actually displaying our to-dos. So I'm gonna put the default values back in our app.tsx for our to-dos. So let me just paste that back in here.
in our app TSX for our to-dos. So let me just paste that back in here. Okay, so I put that back. And let's go ahead and just show them in our jsx here. So I'll make another section here for a ul. Let's make a list item here, and let's say to-do goes here. So we have to map over this. The to-dos are coming in as a prop, but I did destructure them,
The to-dos are coming in as a prop, but I did destructure them, so I can use toDos.map. That takes in a toDo. Let's add the arrow here, and let's make sure to close it out here. Okay, actually we need a key as well for each item, so let's say key equals toDo.id, okay? And hopefully I did that right. Let's see if the toDos render in our browser,
And hopefully I did that right. Let's see if the to-dos render in our browser, and they do, but I forgot the name. So this should be to-do.title, I believe. Okay, but a lot of the times you'll see this extracted into its own helper method, especially when there's a lot of markup. So say we had a few items within the list item here. Let's just say span, and say we had something else in here,
Let's just say span, and say we had something else in here, like an icon, icon or whatever, that's fine. Like I said, sometimes it's cleaner to extract this to its own helper method. So let's go ahead and grab all of this. Let's make a new method called renderToDos, and we should call that, and let's make a function here, okay? renderToDos, doesn't take any params,
and let's make a function here, okay? Render to-dos, doesn't take any params, and we are just doing what I just copied, just mapping over it, and hopefully that should work as well. So back to our app, that is still working. And the reason I did that is because I wanted to show you the return type. Again, TypeScript is really good at inferring the type, and in this case, it is correct.
Now, if we weren't mapping over this and we were just returning some JSX, then it would just be a JSX element. Okay, one more thing on typing events. So say, for example, we had a form here that was an input, so the user can add new to-dos. So let's do that. Let's add a piece of state for that right here. Let's say const, let's name it title, and set title. And let's say useState, let's import that,
Let's say const, let's name it title, and set title. And let's say useState, let's import that, and let's make it an empty string by default. And TypeScript should infer that as a string, so I'll just leave it without the generic definition. Now let's go ahead and make a form down here. So let's just put it here. Let's say form, and I'm not even gonna worry about the action. I just wanna handle the two-way data binding.
about the action. I just wanna handle the two-way data binding and take a look at the events here. So you see this a lot in forms. We have an input, we give it a value of, in this case, our title. And then for onChange, we either do it inline here or we provide a method. So let's provide a method here called handleInput. And every time the user types into this input,
So let's provide a method here called handleInput. And every time the user types into this input, it's going to update the state. So let's add that function, handleInput, and this takes an event. And for now, we'll do any, and we set the title in here. So set title e.target.value. Okay, so let's save that. And let's make sure this works in the browser. So let me open up React DevTools here.
it still thinks that it's of type any. But if we were to do this inline here, VS Code should have a better understanding and should provide us with the correct type. So let's make this an arrow function and let's do the same thing in here. So setTitle(e.target.value). So now if we hover over e, hopefully we get a correct type. And we do.
hopefully we get a correct type. And we do. We see this type here, which we can make use of. If I can get my cursor in there, there it is. Okay, and this should work, but I'm just gonna put it back to our handleInput here and we'll type e like this. And hopefully that should work still. Let's just refresh. And it still works.
