- Now all of the rest of the videos
in this type safety module are going to be about TypeScript.
This one specifically is gonna be
about setting up TypeScript inside of Vite and React
and how to type the props inside of your components.
But I'm not actually going to be teaching TypeScript
inside this section of the course.
I'm expecting that you understand and know how to write
inside of TypeScript to watch these tutorials.
And this is specifically the different things
you need to know about how to use TypeScript in React
because there's a few different gotchas
that you need to know and a few different things
that React has set up that you need to know
before you can use TypeScript inside of it.
So the very first thing you wanna do
is to create your project just like normal.
So npm create Vite at latest.
And what we wanna do instead of select
the JavaScript version, is obviously
to select the TypeScript version.
Then we just need to install everything
and run just like normal.
There we go.
And you'll notice that the files
that are generated are slightly different.
There's not very much difference,
but there's a few differences.
For example, we have these TSS config files right here
where you can configure all your different
TypeScript related setup that you need.
Same thing here inside of our actual package.json,
you'll notice we have a linting section
that we can have in here that has some more information.
Our TSC is being run here to build our TypeScript files.
And we have a few extra dev dependencies
for everything related to TypeScript.
Also inside of eslint we're using
some TypeScript related eslint rules
instead of the normal ones.
So again, just a little bit of extra TypeScript stuff.
And then finally inside our source we have this
vite.env file here.
Essentially that's just hooking up
all the Vite related stuff.
With Typescripts, you have things for like importing
your metadata and stuff like that.
Overall, the code that's actually generated for you
is very similar between TypeScript and JavaScript
except for obviously now you have TypeScript files
that have different types being defined
as opposed to JavaScript files.
So the very first thing I wanna do
is I'm gonna come in here.
Export default function app, just like that.
Just like you would normally do.
And let's just return an H1 that says Hi.
There we go.
And let's just get rid of all these files
that we don't need.
Get rid of all these.
Make sure you keep this .d.ts file in there.
Get rid of all of our CSS files.
And now if we just open this up, we should hopefully see
there we go, that this is actually rendering our output.
Now in order to talk about everything related to TypeScript
what I wanna do is I wanna create a brand new component.
We're just gonna call this child.tsx.
That's important if you're using TypeScript,
use TSX instead of JSX, that's for TypeScript.
We're gonna export our function child just like that,
return an H1 that just says child, there we go.
And we can render that out inside of here.
Make sure I import it.
And there we go, that's working just fine.
Now if we wanted to be able to use things like props
we would need to add them in.
So here I would come in and I would add a prop.
Like let's just say that we pass in a name.
That's the only thing we can pass in.
And that's what gets rendered out
inside of our child component.
Immediately you'll notice we start
to get some errors showing up.
This error right here is essentially saying,
hey, that we don't have a type for our name.
So it has an any type.
And here in our app it's saying,
hey, the prop name is expected.
So the really great thing about using TypeScript
is we get errors and warnings inside of our editor
that are telling us we need to add things
and we also get great type safety and type auto complete.
For example you can see I can auto complete my name
right here and let's just say my name is going to be Kyle.
Now everything will work, but we still have the error
inside of here because we haven't typed the actual props.
In my opinion, probably the best way to type your props
in the most common way is just what you're going to do
is right after all your props put a colon
and then you can define your props in line.
So for example, I could do name string
and that is defining my props in line, no errors at all.
This is a bit unwieldy though.
And generally I like to rename this to an actual type.
So I'll say child props is what the type is gonna be called.
And then I can define my type up here.
Child props equals and I could say that it's going
to be a name which is a string just like that.
Now you can use an interface or you can use a type.
It doesn't matter, they're pretty much the same thing.
In my case, I like to use types.
So that's what I'll be using throughout most of the course.
But again, use whatever you want, it doesn't really matter.
So just by doing that you can see
that we've typed everything properly.
If I go to my app here and I try to pass in something
that's not a string, for example,
I try to pass in a number.
You can see I'm getting an error
and it gives me a nice warning that says
hey number is not assignable to type string.
So obviously this shouldn't be working.
Now the other way that you may see your components
being typed is by using the React.fc helper.
So you would need to actually use here a variable instead.
So it's export const child.
We'll set this equal to an arrow function just like this
and we're gonna type this variable as a react.fc.
This stands for function component.
And essentially what that does is it says Hey
this is a component that is a function component
and this takes in a generic where you can pass in
what your props are.
So in our case, we already have a type
for our child props just like that.
Then what I can do is I can remove this prop right here
for our child props.
We don't need that type anymore
'cause this generic is taking care of that for us.
And if I were to change this back to a string,
you'll notice that everything is working exactly
as it was before.
Now personally I don't like using
this function component way of doing things as much
because first of all,
it adds a bunch of extra stuff onto here.
So for example, in React on your components
you can define things like your prop types.
You can define your default props, your display name
but these things are not really that useful,
especially default props.
If you're using a function component
you can just set your default like this in line
so you really don't need that default props.
So having all those extra things is not really
something that you always need or want.
It also makes working
with some things a little bit more difficult
if you have like name spacing
that you're trying to do inside of your components.
And also just adds a little bit of extra code.
Like we don't wanna write all this extra code.
So personally what I prefer to do is
I just like to write my normal functions
and I just like to add my types on the end like this.
I find it's a little bit cleaner and easier to work with.
Now if you want to actually be able to pass children
down into a component, let's say
that we want to be able to pass in children here
and instead of passing a name,
we're gonna pass down children instead.
So we no longer have a name
and instead we have some children prop.
We don't know what the type is gonna be yet
but that's what we have.
So here, instead of having a name
we wanna pass along some child.
And let's just say child inside of here,
we'll say children, doesn't matter.
And you can see it's printing out fine
and it looks like everything's working fine.
That's because right now we're passing a string.
But if I were to pass this as a div,
that wraps my children
now all of a sudden we're gonna get some errors
because it's expecting not a JSS tag.
So what exactly is the type we should use here?
Well, inside of React, they have a special type.
We can say react.reactnode
and that is going to be a type that is specifically
for anything that can be a React child.
And if we wanna clean this up a little bit
what we can do is we can actually import reactnode,
we can get that from the React library.
Then we don't have to prefix this with the react dot.
Also, if you're importing types,
I highly recommend making sure
you use the import type syntax.
That's just going to make sure
when you actually deploy your code,
it doesn't import any unnecessary code
because this is purely for development only
and we don't need to push this to production
'cause it's just a type.
So now no matter what I pass in here as a children
this is going to work fine.
And since I made this required, it's actually going
to gimme an error if I try not to pass a child.
For example, if I do this with no children
I'm getting an error that says, hey,
children is missing inside of this type.
Now generally if you're working with children
they may be optional.
So you can just come in here, put the question mark
and now it's saying that children is optional.
So again, if I don't pass any children in like this
you can see I'm not getting an error.
Now the final thing I wanna talk about in this video
for passing along props is how you deal with HTML props.
Oftentimes in React you're gonna have a custom component.
Like I'm going to have a custom button component,
export function button, just like this
and let's just return a button
and I wanna pass along all of the normal button props
that I would get.
So for example, here I'm gonna get
all my normal button props and maybe I wanna pass in
something else like if it is an outline button or not,
and I'll add, you know whatever I want,
whether it's a class name or like I'll add a custom style
that's specifically for this like outline.
So I'll just say like border,
one pixel solid red, whatever it is,
it doesn't really matter.
And we'll do that only if we're in the outline.
So outline, then we'll do that.
Otherwise we'll just pass an undefined here, whatever,
not the best code in the entire world,
but that'll get the job done.
So for our types, we can type our button props,
set that equal to here and then we can say the outline.
This is going to be a Boolean, we know that for a fact.
That's working just fine.
Let's make sure we apply these button props down to here.
There we go.
And now if I try to use that button inside of here
And we just say, hi, I am a button.
There we go.
Let's import that component and let's just pass in outline.
I should probably make sure
that this is an optional property
because I obviously don't wanna make that required.
You're gonna see though I'm getting some errors.
If I hover over this it's saying type children
is not assignable to it
because I'm trying to pass along a child,
but I wanna just infer all the types
that a button normally has.
Also, maybe I wanna pass along
like the disabled property and again, I'm gonna get an error
because disabled is not part of that as well.
So in order to get those normal props
that we get from a button
what we need to do is go into our button component
and I wanna actually import a type from React here.
And this type is going to be getting the component props
and it's actually just called component props.
And what we can do with this is we can pass it
whatever component we want to get the props for.
And we're just gonna add that
onto our component props for our actual button.
So here inside of some angle brackets, this takes a generic
I can pass in any element inside of HTML.
You can see I have a massive list here.
So for example, I could do a div.
In our case I want to use a button.
And now if we give that a quick save
our button props is containing this outline custom code
that we defined as well as all of this React related stuff
for our button.
And if we go back into here, we have no more errors.
And also you'll notice I get auto complete
for every single thing that I can pass to a button.
So every prop that is available
on a normal HTML button is available on here
as well as the custom outline prop
that I have defined myself.
So this is really handy because any HTML element
that you want to be able to add the props to,
for example in this type of snare
you can just pass it along additionally
to the actual type you're passing to your props.
And if I did something wrong, like I tried to do a div here
I'm immediately getting an error here.
It's gonna be probably a very massive error.
But essentially it's just saying that hey
I'm trying to pass along all these div types
and they don't work for the button element.
And another really nice thing is
that you can actually do this
with custom components as well.
For example, I could pass in my child component in here
and if I make sure that I import that child component,
we'll get child here from there, just like that.
And now if I just come into here
and I make sure that this says the type of our child
'cause I wanna get the actual type of that,
now my button is expecting everything that I can pass
to my child, which is right now just children.
Let's change it to like name of string, just like that.
That's going to be fine.
Change that to a name.
There we go.
So now inside my button component
this is going to expect an outline as well as a name.
So now here you can see that we have an outline
and we also have a name that we can pass along as well.
And the only reason I'm getting an error is
'cause I have a child inside of there.
If I remove that, you can see now
we no longer get any errors.
So you can use this to do HTML props
or you can get the props of any component that you want.
It doesn't matter what that component is.
This is really useful if for some reason
the actual type is not being exported
because I could just export the type like this
and I could use it like that.
But a lot of times if you're using a library
maybe the types are not exported for the actual components.
So you can just write your code just like this
to get whatever types you need for that component.
And you can use this anywhere.
It doesn't have to be just for passing props
to another component.
You can use this type anywhere you want.