- Hey Jack, thanks for doing this interview with me.
If you just wanna real quick introduce yourself,
talk about your channel, stuff like that.
- Yeah, hi, I'm Jack Herrington.
I am YouTube as the Blue Collar Coder.
So my channel is all about practical advice,
mostly around the front-end, things like Next.js, React,
TypeScript, in this case, and the combination of the two.
I was a principal engineer at a couple of big companies
like Nike and Walmart,
and did a lot of talking at those companies,
and decided, hey, let's just do it on YouTube,
and so here we are a couple years later,
and that's now my full-time job, so pretty cool.
- Awesome, yeah.
In my opinion, Jack is one of the smartest developers
out there on YouTube,
one of the ones with the most experience.
So if you want like really good, expert senior level advice,
like, Jack has definitely have it,
I highly recommend checking out his channel.
I'll link it in the description of this video for you guys.
But here, we're mostly here to talk about TypeScript
and kind of how it integrates with React.
- Sounds good. - Because Jack
is pretty much an expert in all of that.
So I kind of want to open up with a pretty generic question
of just what are your general thoughts
around integrating TypeScript and React?
Maybe problems you run into, specific things
you have to think about because writing TypeScript and React
is a little bit different
than just writing plain JavaScript and React.
- Definitely, yeah because you've gotta define
what types you're talking about.
The nice thing is, I would say from the...
There's I guess three levels of TypeScript and React.
There is this sort of, hey, I'm the guy creating the pages,
that sort of thing, just creating basic components
using useState, using useReducer or whatever,
that sort of thing, and in that world, honestly,
you're not gonna get a lot of TypeScript.
There's gonna be a few little things,
we'll talk about those.
And then kind of moving up from that,
there is like a sort of internal library creator,
should be like, you're creating custom hooks
and then you get a little bit more spicy
in the TypeScript world,
and then there's the sort of library creator,
like you're building like some sort of like
new state manager. Please don't do that.
Please, we're good.
(Kyle laughing)
We have all the state managers we need honestly.
But yeah, if you decide to do that,
just don't get NPM published.
But it's gonna be a lot more complex,
that stuff, is because it's gonna have generics
and yada, yada, yada.
So, yeah.
So from the, yeah, you wanna talk about that first level,
sort of the basic- - Yeah, yeah I'd say-
- Hey, just hello world kind of stuff.
- Yeah, start at the first level.
I feel like 90% of people are gonna be in the first level,
- Exactly. - 9% are gonna be
in that second level and then like 0.1%.
- 1%. - Yeah.
- Yeah, exactly, is gonna be at that top level.
Yeah, so let's talk about the 90%.
So 90% is, you're really only gonna have
a lot of connection to types of,
when you're defining the properties of your components.
And in general, you're gonna use something like React.FC
to define your components.
And then in that first generic parameter,
you're gonna, the less than and greater than,
you put a an object in there
and you're gonna define the properties
and the types for each property.
So you know, you do things like,
hey, it's gonna be a title, it's gonna be a string
and if it's optional you do title question mark
colon string, maybe you get a title, maybe you don't.
That kind of thing.
And then if you have like default parameters,
those would go actually in the function definition itself.
So if like, let's say that it is an option,
that title is an optional parameter
and you want to give it a default value of like,
I don't know, hello, whatever, you'd say title equals hello,
just like you would normally in JavaScript.
So that remains the same.
Yeah, so that would be the number one thing we do
is basically type all your property,
all your components and that's gonna really help you.
So like what's the value of all this?
Why go through all that rigamarole?
Well, as you are, like, invoking those, if you import them
and then you start using them in your JSX,
it's gonna say, Hey, you need a title, all right?
And you gotta type one in or whatever and there you go.
And you can define down to, you know,
does this component take children or not?
All that kind of stuff.
And it's just a really nice way to
add more value to your components, make them easier to use.
- Yeah, one thing, I kind of wanna interject here
is you mentioned using like the React.FC
or like the function component type.
I actually generally don't use that type
and I just use like a generic function.
- Sure. - Mostly because I find
that the React.FC defines a children for you.
- Right. - And I wanna be explicit.
Like, I wanna say this takes children
or this doesn't take children.
- Or it doesn't take, that's right.
- So do you have a preference on which one you use
for that kind of purpose?
- Yeah, if it takes children, I tend to use React.FC
because the children can be, I think it's React dot...
- Like Element or Node or something.
- Element, Node.
I think you gotta get the right one.
- Yeah, there's like 10 different
options and only one's right. - Yes, exactly, exactly.
Yeah, yeah, yeah.
You got to get the exact one right.
Yeah, but that's good advice actually.
So if you're not taking in children, then don't,
don't use React.FC.
I'd say as we use more Next.js App Router though,
we're probably gonna be using children a lot more
than we have in the past.
Like, if you are not used to using children-
And that's weird.
(Kyle laughing) Anything around the whole word children.
- Yeah. - Just like, whatever.
But if you're not used to using components
that compose, like using children,
you're gonna want to end up using that a lot more
because the nature of the interplay
between React server components and client components.
- Yeah, that makes a lot of sense.
'Cause that's one thing I noticed when I'm writing
just like purely front-end only React code,
which like create React App kind of stuff,
I don't really use children that often.
- No, no.
- Unless I have like a really specific use case.
- A container, right? - Yeah, a container.
- I have a box, you know?
- Like, a context is my main thing-
- Box is my whole dialogue. - I use for it. Yeah.
Yep. - Yeah, exactly. Yeah.
But in the next JS App Router world,
they've now kinda layered on this new level of semantics
around children that like, a client component
can contain React server components as children
but can't invoke React server components.
It gets a little, eh.
- Yeah, that's a really good point with the whole FC
when you have children and don't use it when you don't.
I generally just tend to like manually type my children
that way I don't have any FCs in my code.
It's just always the same all the way through,
but it saves you a lot of lines of code
if you just do the React FC and you don't have to remember
if it's Element or Node or whatever.
- Yeah. Do you define functions using function
or const name equals?
- I almost always do function.
I don't use the arrow function.
I find the syntax with arrow functions-
- Which is not gonna be- - A bit bulkier.
- Compatible with React.FC.
So that's done, you know, another issue.
- Yeah, that's another reason 'cause I hated doing it
as arrow component or arrow functions instead.
So I was like, I'll just do it this way.
But yeah, it's kind of personal preference,
as we've all said, but specifically,
if you're not using children, don't use FC
'cause that implies that there are optional children.
- Exactly. Yes.
- Awesome. - Cool.
- I kind of interrupted you so I don't know if you had
anything else you were gonna go on with important things
related to that kind of stuff or...
- Well, so yeah, so now once you get
into that component, right?
So if you're gonna manage state, then you're gonna come up
against useState, useReducer or useRef.
And so useState's actually, you know,
and the typing around that's actually pretty nice.
Normally if you'd have like, okay,
so I got first name is something like that,
now I don't track, you're probably gonna start off
with an empty string and then TypeScript is going to infer
that the type of that state is a string,
which is really nice, right?
The only problem comes around when you have something,
probably like a payload from a server
where it's gonna be like, oh, you start off at null, right?
And 'cause yeah, I haven't gotten anything from the pay,
from the server yet and then I'm gonna go set it
now, you know, it's gonna be like,
well wait, you're setting it to something that's not null
and I don't know what that is, right?
So now you gotta define that this pay,
define the type of the payload and what you do
is then you'd use, again, that kind of
less than, greater than template syntax
and define, hey, I've got this
object coming back from the server
and then you'd use a union type.
So anytime you add one or allow a type
to be more than one different type, you're using a pipe
to basically have like an object if that's what
you're getting right from the storage, probably are,
you know, with the fields in it, yada, yada.
And then you put pipe and then null,
basically say, well you know,
it's gonna start off at null.
So, you know. - Yep.
- That's valid too.
- And one kind of, to interrupt here,
one interesting thing about the useState hook that I find
that if you, for example in your scenario
where you have like a data, you say like,
useState, you give it the generic type
of whatever your data is and if you just don't put
anything inside the parenthesis-
- And then that's undefined, yeah.
- It's undefined and React will actually type,
it'll take your type that you give it
or with undefined, if you just leave it like that.
- Yeah, that's right.
- Which is something that a lot of people don't realize
is happening behind the scenes.
'Cause they're well generic did as this type,
but now it's also undefined.
It's like, that's something you have to keep in mind.
- Right.
So it really depends on whether you wanna use undefined
as your sort of empty state or null.
So if you wanna use null, then you have to add on on.
If you wanna use undefined as is,
cool, then just let it go, which is great.
UseReducer I think is somewhat similar.
Yeah, I think the output time is...
- It's pretty much the same. - Same.
And then useRef I think is defaulted to
like some sort of HTML element
because we use it for that a lot maybe?
- I don't know. - I don't know, yeah.
- The one thing that's interesting about useRef
is if you use it with like an HTML element,
you're supposed to put null
inside the parentheses to tell React
that they manage it. - Yes.
But if you use it- - Right.
- With something that's not that,
you don't put null in there.
That's like one of the most confusing things in my opinion.
- Yeah.
Yeah, it is. It's very confusing.
But it kind of, I understand sort of why they did it.
They want it to be really easy
and if you, the typing can get very, very specific
about the type of element that you put it on, you know,
and that you hit up against that later
with like events and stuff like that.
- Yep. - It's a little bit nicer.
But yeah, I often actually also use useRef for
managing state that you don't want
a re-render when you change it.
- Yep. - So you just change current
and it doesn't matter.
I mean, there's certainly things like that
that you wanna hold onto and then in that case,
you're gonna be in the same situation
where you want to go and put some typing
on what that's gonna be
if it starts off at undefined or null.
- Yeah, whatever it is. - Yeah.
- Yep. - Yeah. Cool.
- Awesome. - And then, let's see,
so the next area would be probably event callback.
So you're on click, things like that.
You can, if you want the event details,
then you're gonna have to put on, you know...
Yeah, if you define it as like a callback,
then you're gonna need to put in like the type of the event.
But if you actually just define it
in like an on-click handler, then you don't
because it knows because I'm on a div or whatever,
it's gonna give you the right types.
But there're actually, yeah, there's literally
like a type for almost every various HTML element,
which it can be kind of a pain, but they are different.
I mean, different ones have different events
that they can generate, so.
- Yep. And the nice thing is they pretty much,
like, when it comes to HTL elements,
they all start with HTML something.
So it's kind of easy when you're auto completing.
- Right, yeah.
- And same thing with the events,
they all end in whatever event.
So it's a little bit easy to kind of find the right one.
- Yeah, the other thing I use a lot actually is,
and I work on Mac, so this is what works on Mac,
but like Cmd+K, Cmd+I will give you a popup
of whatever the typing is that you're on.
And so if you don't know,
you can basically just add in an event handler
on whatever it is, on click or whatever,
see what event is with Cmd+K, Cmd+I,
and say, oh, that's the type, you know?
- Yep. - Just copy it.
- Yep, I do that all the time. - Paste it later on.
Yeah, exactly.
- What I do is I just hover over the variable
and it'll pop up the type and I just copy it
straight outta there, just paste it down.
I'm like, okay, yep, there's my type.
- Right, but if you're ADHD like me
and me want, yeah but I need to now.
(Kyle laughing)
You know? - Yep.
- Hit Cmd+K, I need it know.
- Yeah, I didn't even know about the Cmd+I.
- Waiting to get Copilot to like complete.
You're like, okay. (snaps fingers)
I'm waiting, I'm waiting.
- Yep. - I'm waiting for my fetch,
whatever it is. Yeah. - Nice.
- Okay, so what else?
Sometimes it depends, there's also like a strictness level
you can apply to TypeScript
and some folks will hard code that they want return types.
And so you might end up having to specify those
on your React components as well.
But I think that's just basically the similar sort of thing
to what children was producing.
And that's kind of nice.
I mean, if you, I don't know,
it keeps you from accidentally like returning a raw object
or something like that, which is gonna blow up a re-render.
- Yeah, yeah. - Or render.
- I personally don't like defining my return types
- Yeah, I don't... - in TypeScript.
But like you said, some companies will require it,
but if I have the option to,
I like to just leave it inferred.
- Oh, yeah.
- Because Typescript's so good at that.
- Yeah, exactly. Yeah.
And I've rarely ever run into that as a problem.
Normally, it's when I'm putting
like, some value into the JSX
and it's like, oh wait, well that was a,
instead of being a string or number, that was an object.
- Yep.
- And then that blows up. - Yep.
Okay, one...
Did you have anything else, I guess,
about like that 90-ish percent?
- Yeah, that's really where
most folks are gonna interface with it on their day-to-day.
I mean really, I mean another thing is
when you are working with payloads on the server,
you're probably gonna use those in multiple locations.
So being able to create or export those,
define those as an interface or a type,
you know, I tend to use interface for payloads
and types for things like functions,
but you could use types to specify a payload,
but you want to define those sort of as a known type,
and then when you're looking at the code, it's like,
oh, okay, this is a, a return value
from this particular endpoint or whatever.
And that just makes the code a little bit more readable.
And then as you are maybe passing it onto another object,
you're not redefining it again.
And so you wanna dry, you want to keep not repeat yourself.
- Yeah. - Kind of only once.
- That actually leads really well
into another kind of question I had planned,
which is kind of around like folder structure,
file structure and like, where do you store your types?
Like for me, I like to put my types as close
to where they're actually used as possible.
But when it comes to things like-
- Yes. - Payloads or other types
that you use all over your app,
it could become hard to determine
where is that core place it's used
'cause it's used everywhere, you know?
- Right, but if I have a fetch function
that's gonna go get something from that endpoint,
that would be the ideal location
for me to go and put that type.
- Yep. - Because it's right there,
this is what's gonna be doing the work.
And so go and define the type
and then as you are returning the fetch,
because I think fetch returns like an any, maybe any...
- I think it's, yeah, it's any.
- It's very liberal. - Yep, it's any. Yeah.
- Yeah, it's very liberal about how to use the output,
but you really want to cast that.
So you wanna say as, and then cast it
to whatever that payload type is,
so that as I'm getting that, as I'm calling that function,
and this is when you're sort of migrating
into like the internal library author kind of thing
'cause you're creating like this fetch
that's maybe reused at various parts of the application,
you wanna make sure that that fetch's response
in returning to you that either you know,
an error or I guess a throw, whatever.
But if it comes back, you get a promise to that data type.
And so then you get, like,
a really nice strongly type response
and as you're putting it into your JSX, again,
you're getting that sweet hinting to like,
oh this is, you know, this value or whatever.
Yeah, so that's really handy.
And then I guess there's a few little,
so there's these utility types
like, and one in particular is promise.
So if you're gonna return a promise to something,
then you just literally use capital P Promise
and then in again, the less than greater than,
you put whatever type.
You know, so there's a promise to a Boolean,
you know, you put in Promise Boolean, whatever.
That's how. - Yeah, that makes sense.
Another thing, so let's say that you have,
you get like some data back from your API
and it's in whatever format, and then let's say that you,
in a certain subset of your application,
you need that data combined with some other data
to create essentially a new type of data.
And you use it across like eight or nine components
in that subsection of your application.
Where do you generally think about
creating the type for that?
Do you create it in the, like, parent component
that kind of composes that data
and then you just pass that down from there?
Or do you have another place you do that?
- I think wherever it's gonna be augmenting that data,
then you have that type and then the ampersand
and then whatever additional fields
that you're adding to that value.
And then you define it right there as you're doing the work.
And oftentimes if you're doing like context,
yeah, you define it inside of that context.
- Yep, that makes sense.
- You know, you don't necessarily,
context is really nice in that once you
have useContext set up properly
and you've got maybe a custom hook
that does the, wraps the useContext,
then it's gonna give you back the type, right?
It's gonna give you all the information.
You don't need to export the type, it's just already there.
- Mm hmm, yep. Definitely.
Yeah, I love context when they're typed properly.
Like, the setup steps are kind of annoying,
there's little bit of boilerplate there,
but once you get it set up, it's so nice.
- It's not bad. - No, it's not bad,
but it's just like, ah, come on, I gotta do this again.
You know, it's like 10 lines of code
you had to do every single time
and I'm just like, ah.
And there's no easy way to copy/paste it
'cause like all the code is like specifically
named whatever your context is.
So it takes like 10 seconds,
but it's 10 seconds of my life I wish I had back.
- Yeah, that's true.
And then there's always that little weird thing
that you are like, okay, so my little hubber custom hook,
should it just assume that it's in a context
or should it throw, but it's not in a context.
And it should throw.
- Yeah, I always have it throw.
- Like, the extra three lines or whatever.
extra, you know, the if and then the curly and then throw.
- Yeah. I just also hate manually casting things
in my TypeScript unless I really, really need to.
So like if I have the option-
- Oh, right. - To just wrap it in an if
and throw instead of manually casting,
I'm like, oh yeah, that's way better.
- Yeah. Yeah, bangs are bad in TypeScript
are just the same way they are in CSS, you know?
- Yeah. - Nothing's that important.
But basically what a bang will do in,
an exclamation point or a bang in TypeScript
is basically saying, hey, this is,
if you thought this was gonna be null,
I can guarantee you that it's not null.
And generally speaking, TypeScript is really smart.
So if you have like an area where it's like, okay,
I only wanna run this code if this value is not null,
then if you put that in a conditional
anything in that conditional, it's going to know,
okay, if you start de referencing this,
then at least I know here it is not null
'cause you've checked.
Right? - Yep.
- And it's smart enough to know that.
One thing that was really nice, actually,
when TypeScript came out, I think it was,
TypeScript came out with this first
and then now it's in just JavaScript,
which is the null coales-
No, not null coalescing.
Well, yeah, null coalescing.
- Yeah, and then there's optional chaining.
- Yeah, and optional chaining, right.
- Yep. - Exactly.
And that's just, oh. Mm.
- Yeah. (laughs) - That was so good.
- Especially with TypeScript 'cause it infers
the types so well from it.
So like, it's almost magic
how well the types get inferred from all that.
- Yeah, yeah, yeah.
Especially if you've got like those really deep, nested,
nasty results, you know, like, oh, ugh. Yeah.
- Awesome. - So yeah.
And I guess like level two, if you want to get
to that level, would be like custom hooks.
So, and then I would say that's actually one
where I do think you should probably put
typing around the return value, unless it's trivial.
- Yeah, especially if you're like doing something
that returns, like if you're making
a used local storage hook,
- Yeah! - That's a great one
to do custom wrapping around 'cause you're essentially
having like a really complex return type for that.
- Yes, exactly. Yeah.
'Cause you're gonna have a getter,
you're gonna have a setter, you're gonna have, whatever,
you know, an observable value, whatever,
you know, however you wanna do it.
And then you start getting at things like
a little bit of generics.
I don't actually think generics are all that bad.
They're not that difficult.
But as an example, like,
so you can have your local storage hook
and you're like, okay, well what's gonna be in there?
It's gonna be, I dunno, string or an object
or something like that.
So, but you don't wanna have, you wanna have one
used local storage hook that works for anything.
And so what you can do is you can basically just do
a generic syntax where you can put,
like, before you define the function,
again, that less than greater than,
and then give it a symbolic value, like a symbolic name.
You know?
In fact, I just kind of word it off using,
a lot of folks use T for this as like a generic T
- It's like the lazy way of doing it.
- It is, like, you know, tell me what you,
tell me what you're doing here, you know?
And I would say like maybe data type,
I don't know, something like that.
Something at least somewhat more informative. I don't know.
- Less intimidating, too, when you don't have
just a bunch of T's everywhere and K's and Y's and V's.
- Oh, right?
- Like, why'd they even choose these letters anyway?
- Right. Yeah, yeah, yeah.
Well, K and V kind of make a certain amount of sense.
- Yeah. - Much better
than I J K L, that's for sure. - Yeah. Yep.
- And then you can go and use that anywhere in the code.
And what it'll do is it'll give you
a nice type safety and reusability.
So you can only have that one use local storage hook,
but you can use it for any data types.
You may like, I guess give it different keys and stuff.
I don't really use local storage all that much.
Normally, it's just like auth and then the auth provider
just does it for me sort of thing.
- Yeah, the nice thing about generics, I find
that for the 90% of developers is most of the time,
if a generic is well written, you don't actually
need to really mess with it much at the 90%.
Like, half the time the actual generic type
will be inferred for you.
- Yes. Yeah.
- And then when you need to supply it,
it's not usually that complicated.
So I like that for like the 90% of people,
that generics are just kinda one of those things
you need to know exist, but most of the time,
they just resolve themselves for you.
- And I would say don't over-specify.
Like, if the inference has picked it up,
like, if the inference says, oh-
Like, if you got useState, some string value,
you know, whatever, it says a string,
it's not gonna be anything other than a string,
don't go all, oh, okay I wanna go and put in,
you know, generic string, like, it knows.
It's good, it's good. - Yeah, exactly.
- It's got this, right? Fine.
You don't need to, yeah.
You don't need to do any more than that.
- And that way, like, in the future,
if you update your code and now it's a string or a number
like, TypeScript can possibly be smart enough
to figure that out already for you.
Like, you don't have to go through
and now change where you've specified the generic.
It's kind of nice that it can just infer everything for you.
- Yeah, and it's really good at that.
I mean, I would say as you're migrating
your Jot JS files to TS files,
honestly in React most of the time, it's like,
you do the props, you may do the state
and that's about it, honestly.
- Mm hmm. Yep, yeah.
- Usually that's good enough.
- I've noticed that most of the time when I'm writing
TypeScript code in React that the actual JSX
looks pretty much identical.
Like, there's maybe- - Oh, yeah.
- A few things that are different, but really what changes
is your function definition with your typing
and then like you said, you have a few generics
on your useState maybe and that's about it,
which is really nice.
- Yeah, I don't think there's any changes on JSX
- Yep. - That I've really seen, no.
- No, unless you're like doing something really weird
with like a callback where you have to do
some typing inside of a callback,
but that would be pretty niche.
- Maybe. Yeah. - Yeah.
That'd be like...
- I have seen, like, I have seen generic components.
Very rarely, but like- - Yeah, very rarely.
- A classic is like a data table, you know?
It's like, oh, I'm gonna give you a data table,
the row definition is some sort of whatever,
ID food, blah, blah, blah, blah, blah. Right?
And what you want is you want when you get
like, the click handler to like, hey,
you selected this row, you want to get that data type back
and so that you'll use a generic to define
this is the type of each row in the dataset.
And then, when your click handler is gonna define,
like, okay, it's gonna get back that type.
And that's really nice because then like you've got
a generic table where the typing is really nice
and flows through the click handler on the other side.
That's about it.
I think that's probably the only thing I can think of
in terms of like a generic component.
- And the nice thing about generic components
is most of the time you're passing props along
that infer the generic for you.
Like, if you're doing a generic data table,
you're passing along your rows
so it already knows that type for you.
So you don't actually have to manually define it.
- Yes, yeah, yeah.
Right, so you basically say
a generic is like row type, right?
And then you say data and you say is a row type array.
Right? - Yeah.
- And then whatever I'm giving you is that row type
and then your on click handler is literally just, you know,
I get, whatever, cell click or whatever
call, you know, colon row type.
- Yep. - That's it, ta da. (laughs)
- Okay. - Very easy.
- So I got another question for you.
This one's gonna be a bit of an interesting one.
- Oh, cool.
- So it'll be kind of a two part question.
First, I wanna talk about prop types.
If you're using TypeScript,
what are your opinions on prop types?
Mine is you don't need 'em.
- I haven't used them in years.
- Yeah, okay good. Good.
Second question then, since we got,
we both agree on that is if you're converting an application
from JavaScript to TypeScript
and it heavily uses prop types,
what is your best opinion
on how to tackle that kind of solution?
'Cause you have some types,
they're not very good types, but you have some types there.
They may be wrong, they may not be,
you know, you can't really know for sure.
But like, are you able to leverage that
to help you convert over to TypeScript,
or what are your opinion to that?
- I think so, yeah.
It's been a long time since I've seen one of those,
but I would say sure. Yeah, absolutely.
And the nice thing is that it's going to,
so what those that, what the TSS types are gonna give you
that prop types don't is they're gonna give you
build time checking where prop types
is just runtime checking.
And if you're not looking at the console, right?
It could be barking all over the place
that you're not passing the right thing.
You're like, oh, okay, whatever.
You know, eventually you also might see it, right?
But in terms of TypeScript, you take those prop types,
you translate them into your actual types
of the properties coming into the component.
And now as you're rerunning the code base,
literally it's like, oh, you're not passing that
right here and it's gonna break in the build
before it goes to the browser.
And you're not having
to look at the console log all the time.
- Yeah. I remember using prop types back in the day
and that was the worst part.
It's like, you write them and you look in the console
the first few times, but then you're like,
you don't have the console open all the time.
So then you write the rest of your code,
you forget to check the console,
you push it up to production,
you realize, oh crap, I actually had it wrong.
- Yeah, they didn't pay off.
- No.
- You know. Really?
They didn't.
You know, at the end of the day it's like,
what did we get out of that again?
Like, maybe runtime checking. - Yeah.
- I would've liked if there'd been some
documentation hook or something like that.
Like, I like things that are like a multiplier.
Like I do a little, I'm lazy, I do a little bit of work
and it does more than what I put into it.
In terms of TypeScript, it's doing build time checking,
it's doing great hinting.
Like, I'm getting a lot of return on my meager investment
to add some, you know, few types here and there.
- Yeah, definitely. - Yeah.
I guess the only other thing back to utility types
for a second there is, like, record,
which is one other utility type
I kind of use on the regular.
- Yep. Yeah, record's good because it's pretty much
how you type objects that are more generic
than just a straight object that you know the types of.
- Yeah.
- Another kind of question related to the same vein is when-
I don't know how much experience you have with this,
so we can skip it if you don't, but-
- No, no, no.
- When you're converting an application
from JavaScript to TypeScript, what is your approach?
Like, what do you generally try to focus?
I mean, you obviously probably focus on the core code
that the application is the most important,
but like, when you figure out what you're gonna work on,
where do you start? Do you start like with the components,
do you start with utilities,
do you start with the fetch requests?
Like, where do you generally start with that kind of stuff?
- That's a good one.
I would either probably start with the leaf node components,
you know, the ones that are way down the stack
and kind of work back up,
or I might go from the fetch side.
- Okay. - Yeah.
- That makes sense, yeah 'cause the fetch
is kinda like where your data's coming in.
So in both cases you're kind of starting at the bottom.
Like, in the fetch case you're starting with,
like, where your application data starts
and with the component way, you're starting with,
like, the smallest, easiest to get to component
and building up from there.
So in both cases, you're like going bottom top.
It's just, are you starting with the display
or are you starting with the data?
- Right, and I think it's also good to keep in mind
where are you gonna get some good bang for the buck, right?
And I think that the business logic is really
where you want the most checking.
I think properties, kinda cool, kinda, yeah, that's great.
Good hinting, da, da, da, da, da, you know, whatever.
But in terms of the result coming back,
one of the big problems that we see sometimes,
like, oh, you're using the wrong key
on the result data from the server or something like that.
You know, they changed it
from status code to status or whatever, right?
And you didn't pick up everywhere in the code
that status code became status and so, boom. Right?
And that's what you wanna avoid.
- Yeah.
- If you type those fetches and downstream,
I mean, the JavaScript can just ignore it,
but the TypeScript can pick it up.
Yeah, you're gonna get that nice payoff
when those types change.
Which is honestly, I think there's a perception out there
that like TypeScript slows you down in these kind of things.
Where in reality, I would say in large code bases,
it actually does the opposite.
It's like, I have-
I remember at one job I was moving, oh wow,
it was huge refactor of taking a electron application
and then getting it into a mono repo
and making a Next.js application
and then having both the Next.js application
and the electron application
using the same components. - Oh geez.
- In a library and just massive moving around of code,
just like, you know, like dump truck kind of stuff.
Like, kind of thing.
And thankfully, it was all in TypeScript
and that saved my butt.
- Oh, yeah.
- It was 100%. No way I could've done that.
I mean, I could've, but it would've been a huge, I would've-
- There been so many errors, too.
Like, you would've never caught until it's way too late.
- Oh yeah, for sure.
Like, it would just, you know, been thrown out
and like, oh, I have no idea.
It would just have been like long, okay,
comment this out, comment this out,
eventually try and get back to something that works
and then like recom, like, ugh, mess.
- Yeah.
- So yeah, that kind of stuff, like on huge code bases,
TypeScript is just completely invaluable.
- And honestly, I think it's invaluable
even on small code bases.
'Cause I feel like most of the people that perpetrate
that TypeScript slows you down
are the people that haven't really spent the time
to learn TypeScript, even just like spending
a few hours on TypeScript
is enough to kind of give you a good grasp.
- Yeah.
- And the first few projects you write in TypeScript
are going to be slower 'cause you're learning TypeScript.
It's just like when you write React,
it's slower at first until you get used to it.
But once you get used to writing in TypeScript,
it may be takes you 1% longer to write your code
and then you save a hundred percent of your time
in the future because refactoring
is so much easier, so much nicer.
- Oh, right. Absolutely.
Yeah. And it just comes naturally.
As you're just writing, it's like, okay, that's a string.
That's a number.
- Especially 'cause when you're writing your code,
you kind of already know what the types are in your head.
So writing those out is pretty easy.
But coming back a year later and remembering
what those types were without the TypeScript there,
it's like, I don't know what that was back a year ago.
You know?
- (laughs) Right?
- Like, I don't even remember
what I ate for breakfast yesterday.
How am I supposed to remember
what my types are from a year ago?
- (laughs) So true. So true.
Do you use Copilot?
- I've used it.
I don't use it for any of my tutorial videos
'cause I don't wanna overwhelm people.
- Yeah, I know.
- But I use it when I'm writing code on my own
and I think it's amazing for actually typing things for you.
I've taken JavaScript code- - Yeah, I was gonna say.
- Converted it into TypeScript and it just does it for you.
- Yeah, I know.
It's crazy, right? - Yeah.
- It is so good.
It's looks at like, oh, first name.
Well, that's gonna be a string.
- Yep. - Okay.
Yeah, I guess you're right.
Nine times out, you know, a hundred times out of a hundred.
- Yep. - It's not gonna be a number.
- But it's even, slightly off topic, it's even really good.
I took a React code base that was Gatsby
and I converted it to Astro and Copilot was really good
at helping me just easily get rid of all the monotony
of like rewriting all it into Astro.
'cause it's very similar code.
It's just you define your props and stuff a little different
and it just did all that for me.
I was like, wow, this is really nice.
- What did you do about the GraphQL?
- So I wasn't using much of the GraphQL
'cause it was like a static site.
Like, it was a sales page is what it was.
So there was like no GraphQL in there.
So that was a little bit different
than what most people run into
because mine was a very like static page.
- I guess. Wasn't that the big selling point of Astro
is the whole like GraphQL like-
- Yeah, I think that was the big benefit of graph-
Or of, what was it? Gatsby.
Yeah, the GraphQL was the big benefit
and then everybody realized like, that's kind of overkill
for just writing a blog. - Yeah, it is.
- Yeah. - Yeah, it was such a pain.
Like, it was very hard to get to it.
Like, oh this kind of...
Had to learn a whole bunch of new concepts
and yeah, not great. - Yeah, definitely.
Okay. - Okay.
- I got one last question for you.
- Okay, hit me. I love this.
- This last question is gonna be,
what is the biggest mistake or like foot gun
that you see people run into when they first get started
with writing TypeScript and React?
I'm sure there's a million, but like what is the one
that you really see people run into?
- TypeScript, though.
I mean, I know React foot guns,
you know, use effect.
- Yeah. (laughs) Yeah, the whole thing's a foot gun.
- But I'm thinking, like, what, Type...
Hmm. That's actually a good one.
Like, I've definitely, I've seen people
try to over specify types, for sure.
- Mm hmm.
- Hmm.
I don't know.
I'm kind of blanking. What are yours?
- I think for me the biggest one is the how useRef works
with like passing along null and not passing along null.
And kind of the same thing with context.
Like, when you define a context,
you have to pass along null as the default value
unless you have a default value, like, requires you to.
That one at least they warn you about.
Like, they throw an error if you don't.
But with the useRef one, it's just like,
let's hope you read the fine print
of the React documentation for that one
'cause that's the only place they mention it.
- (laughs) Yeah, okay.
Well yeah, as I say, I don't think there's,
there's not that many.
- No. That's kind of the nice thing, though.
If you're in that 90% or even the 99% group,
it's like, you don't have that many complicated things.
It's just, as long as you kind of know
how the different hooks work,
that's 95% of writing TypeScript and React.
- Yeah.
I guess like
sometimes, like, type synchronization. How about that?
I mean, TRPC exists almost
to solve the problem of type synchronization
between the client and a similar,
a server on a similar stack. Right?
If you have a backend server that's also on Node,
you can use like TRPC and so, yeah.
Yeah, well getting TypeScript set up
so that those are accessible across that boundary
can just be a little bit tricky.
But usually the document, usually if it is like a project
like TRPC, they've got great documentation
on exactly how you need to change your TS config to do that.
Things like NX handle all this stuff for you outta the box.
Yeah, those are the ones
that I find probably the most tricky.
In my weird world of, like, MICRA fees
and module federation and that sort of stuff,
there's a whole thing about like TypeScript,
but that's just in this sort of arcana world
of like big companies who want to have massive projects
and stuff and we use micro-frontends
and they're are typing, pain in the butt.
- One thing that's also kind of nice
with the new way that Next.js is doing things
with like server actions and stuff like that,
I find that you have less of that boundary to worry about
because you're writing all your code kind of in one place.
You don't have to worry about that type boundary
nearly as much as doing a fetch request that returns any
because your server component or your like server action
kind of already has that typing built in,
which is really nice.
- Yeah, that's a really good one.
That's a great advantage to assays that I didn't talk about.
Actually, just released a video this morning.
I didn't go there. I should have.
- Time to hit the edit button. - Oh, no. Oh well.
- You know, oh well.
- But yeah, no, I mean I guess, where-
Hmm.
I'm trying to think where we put the type
of the payload coming back from a rest,
like, just a basic API route.
Probably in the API route, I would, maybe...
- Probably, yeah.
- Yeah.
- That's a tough one.
- I'm not loving that.
- Because if you do just like a plain server action,
though, not necessarily like API route,
a lot of times you can just infer the type.
- Oh, yeah. - Return from function,
which is nice. - Yeah, yeah.
That's a huge advantage of a server action
is the typing is beautiful and it's all inferred.
- Yep. - I'm just wondering,
like, okay, so a downside on server action is
it's this post request or whatever, it's handling
all the format and structure of that API request,
which is really happening, there is a request
that is happening off the client.
But if you've got like a mobile app
or a desktop app- - That's true, yeah.
- And you wanna have the same API,
it's like, they're not gonna wanna do that,
so you're gonna have to have an API route.
- Yeah, and then you just go with like TRPC. (laughs)
TRPC I think is honestly the best for that kind of stuff
where you have an AP and you want to consume it.
It's like, I love TRPC.
- Yeah. Yeah, yeah, yeah.
And it works. It works on App Router now too.
So that's cool.
- Yep. - Yeah.
- Awesome, well-
- I don't know, is T3 updated yet with the...
- I think I haven't seen the video,
but Theo released a video recently
where they said they were updating it.
I don't know if it's out yet, but it's like in the works
of being updated for App Router.
- Not that bad, it's not hard.
I mean it's a few little things.
But I mean it's not gonna be a seamless upgrade,
but no App Router upgrade is gonna be seamless.
- No. Yeah, no, definitely not.
I guess that's kinda all the main questions I have.
I don't know if you had
any last thoughts you wanted to mention.
I don't wanna take up all your time, so.
- I guess, oh, there's also, (clears throat) sorry.
(Jack clears throat) (Kyle laughing)
There's also, so.
- There's what, sorry?
- State managers. - Okay, yep, yep.
- So things like Redux, Redux Toolkit,
Zustand are popular ones, Jotai now is very popular.
Those, Zustand is really easy to type.
You basically just, again, it's a generic syntax
that has the type of your store, if you're gonna use that.
And then Redux Toolkit is actually really good
when it comes to typing Redux.
So if you're gonna use Redux, use Redux Toolkit
and you get good typings.
- Nice. I'm just waiting for Tanner Linsley
to release a state library.
'Cause everything he does is perfect with TypeScript.
- Oh no, please, no.
- (laughs) Everything he does is really easy to type, so.
- Yeah, that's true. - But yeah, like you said,
we don't need any more state managers.
There's like a thousand of em. - No, no, no.
We got a lot of good ones, got a lot,
and good ones, representative good ones
in every single model of state that you'd want.
That I can think of. - Yeah, for sure.
Awesome. - Awesome.
Yeah, this has been great.
- Well, if you don't have anything else,
I really appreciate you taking your time.
But like I said, I'm gonna mention
or link his channel in the description.
It's a goldmine of great content.
- Thank you.
- I'd highly recommend checking it out.
- Yeah, and thanks.
Thank you for having me, this is wonderful.
And it's always a great, it's always fun.
- Yeah, I agree. I love talking with you.
- All right, check you later, sir.
- See ya.