Transcript
00:00:00 Kent: Hello everybody, this is an exciting day. We get to talk with Matt Pocock about TypeScript and other things. So if you haven't heard of Matt yet, then you're in for a treat. Matt is just a lovely person to chat with. He Has a very nice voice that if you take
00:00:21 any of his courses, you will hear a lot, which is great. And yeah, we're excited to chat about the thing that Matt has recently been most excited about, which is TypeScript. But before we get too far into that, Matt, would you like to give an intro to yourself?
00:00:37 Matt Absolutely. Well, I feel a tremendous pressure to make my voice sound even better than it supposedly is as well. So that's a nice little subplot throughout this whole interview. No, I've been full-time talking about TypeScript for about 6, 9 months now, I guess. Before that, I
00:00:57 was working at Vercel as a developer advocate and then at a company called Stately, which when I was there, I was part of the XState core team. And XState is a complicated sort of state machine, state chart library that I know that you really like, Kent. And this, I think maybe how we had our first interaction as well, maybe in the Stately Discord as well. And I think
00:01:18 like when we were working on X state and stately, we had a lot of complicated TypeScript problems to try and solve. Oh yeah. I was really passionate about, state machines and state charts and through battling with TypeScript and working with my colleague at the time called Mateusz Brzezinski, who's a massive TypeScript expert. I got exposed to all that stuff and got really excited
00:01:38 and interested in it and then start posting videos about it and went full time and here we are.
00:01:44 Kent: That's interesting how that happens. I think I've kind of shaken this idea off recently, sort of, but a year or 2 ago, a lot of people just saw me as the testing guy. And because I created testing JavaScript and testing library and all
00:02:04 that. And I don't know if this is the same for you, but I never, never planned on being the testing guy. It just happened because of the things that I was interested in and things I was working on, the problems I was trying to solve, which, yeah, I think it's kind of interesting how it just kind of happens naturally.
00:02:24 Matt Totally. I think I just posted my first video on TypeScript. Before that, I'd just been posting about XState. I was kind of the unofficial dev rel for XState at the time, along with David Corshede, obviously. And I posted a video about TypeScript. People loved it. I posted another 1. People loved it. And suddenly I was the TypeScript guy. People were calling me the Rodney Mullen of TypeScript. I think that
00:02:45 quote went around for a long time. Yeah. And that's still, I am the guy. And so I think, yeah, it's strange when people you don't know, start tagging you on things and start saying, help me solve my TypeScript problem. I'm sure you get that all the time with many, many different things. In fact, you're not just the testing guy. You're probably actually the React guy too. It's probably you and Dan Abramov getting all
00:03:05 the love.
00:03:05 Kent: Yeah. Yeah. That's exactly kind of how, how it works, but like, I'm sure you have a, an idea of how you became the guy. And, I can say that, for me, I became kind of the testing guy because I created Testing Library, but also because I started, I would reply and
00:03:25 I would answer the questions. And I definitely see you doing that with TypeScript.
00:03:30 Matt Yeah, it turns out if you reply, they just ask you more. So don't feed the trolls or don't give out useful information or people will think of you as the guy who gives out useful information.
00:03:41 Kent: Yeah, which, you know, that plays well into your hand as an educator because you definitely want to be seen as that person. And I always saw that as kind of like a job security thing too, because like if there's ever a downturn or given the slight downturn that we've experienced, I'm Sorry, I shouldn't say slight, like some people
00:04:02 have lost jobs and stuff, it's not slight for them for sure. But the downturn we've recently experienced, it gives me no sense, a small sense of security knowing that in that event, the people who are seen as the most skilled are the ones who are going to keep their
00:04:22 employment. And so that was my justification to my wife when I would explain why I spent so much time on Twitter and answering people's questions for free and doing open source. All of that was to like keep myself forefront in people's minds for that sort of thing.
00:04:40 Matt And it keeps me sharp as well. That's what I feel. I just get the sense that I feel, I imagine you maybe feel as well that I feel a little bit divorced from kind of like the day-to-day development. I haven't been on JIRA in a long time. Yeah. Like I don't have a manager or anyone. I haven't like got a burned down chart or anything sort of like
00:05:00 corralling me to do stuff but people just asking me stuff all the time and giving me the insight into their day-to-day, it keeps me sharp and keeps me interested.
00:05:09 Kent: Absolutely. That was actually 1 of the things I was worried about when I went full-time teacher back in 2019, was just that, like, I would lose touch with what it's like to be a real engineer on a team and stuff. And I definitely remember what it was like at big and small companies, PayPal and things. I had a small stint with Remix, which I
00:05:29 think kind of helped. And that was a little different experience than I'd had before as well. But yeah, it's important to stay close to what that day-to-day development is like. Like you and I both spend a lot of time developing software, whether it's open source, reusable packages or actual applications.
00:05:51 I was actually worried about that too, but it turns out there's no shortage of coding projects to work on, even as an educator. But yeah, it is kind of interesting, the regular day-to-day work that developers have to go through that, yeah, I'm glad
00:06:12 I don't have to deal with regularly.
00:06:15 Matt Yeah, there's a whole subset of stuff that I just so happy that I don't have to do anymore. It's it feels so good. I mean, but I don't know. There is a part of me that it chooses to get back to at some point.
00:06:26 Kent: Yeah, yeah, I know the feeling.
00:06:27 Matt It's kind of you want to go back to school or something and kind of relive your glory days. You know, that's how I feel. I want to go back knowing everything I do now and knowing all this sort of extra edgy stuff I've got as an educator and just think, oh, I could absolutely smash that Jira ticket. I really could.
00:06:42 Kent: Yeah, that's for sure. Maybe 1 day or you make your own company or something. Cool. Okay, so yeah, let's talk about TypeScript a little bit. First, let's get this, I guess, this first topic out of the way. Should people use TypeScript
00:07:02 at all? Like, why is JavaScript not enough?
00:07:07 Matt I think when you look back at the reasons they created TypeScript, the reasons they created it is that they thought at the time JavaScript just sucks really. And it really did suck at the time. This is like 10, nearly 11 years ago. And JavaScript really was in a place where it was just not functioning well for large applications. You didn't have a sense of what
00:07:27 modules were. You didn't have, like, really all of the tools that we have today to build large applications and make nice modular things that lots of people from the same team can work on. And I think there's still a lot of those issues hanging around today in JavaScript. But the thing that's really painful about modern JavaScript today is that
00:07:47 the IDE experience is so bad. Like when you go into a JavaScript project, it's kind of like you're delving around in some kind of complex arcane CSS, right? Like you're just scared to touch anything or change anything because you have no idea where those ripples are going to go out to. When you're using something like VS Code, which I think a lot of the industry is on right
00:08:07 now, VS Code and all IDs are integrated really closely with TypeScript. When you use TypeScript, you just get so many more powerful tools at your disposal that you just wouldn't have otherwise. You get autocomplete, you get in IDE errors, you get loads of tools like refactors, go to definition, and you get kind of
00:08:27 like a English teacher just over your shoulder the whole time, just like watching you write down your stuff and giving you little red squigglies, you know, when you're doing things. And you can hand in your code at the end of the day and go, does my code work or not, according to your thoughts? And the teacher will go yes or no, which means you can kind of integrate it on CI
00:08:48 and your CI can tell you, okay, does this look like it's going to work? And most of the time it will catch things that you wouldn't have got otherwise. So when Airbnb migrated into TypeScript, I can't remember what the exact figure was, but it was something like 38% of all of their bugs they shipped to production could have been prevented by TypeScript. So it's just, I mean,
00:09:08 it's like, at the end of the day, you get a more powerful IDE, you ship fewer bugs, and to be honest, I just feel better working with TypeScript. It's just feels like my tools are more powerful.
00:09:19 Kent: But doesn't TypeScript kind of tie your hands so you can't be as expressive or like, yeah, like there are features of the JavaScript language that you cannot use to their full extent if you're using TypeScript. So doesn't it limit you?
00:09:36 Matt So TypeScript, basically TypeScript describes JavaScript. And so the more complex language that you're using within JavaScript, the more complex your TypeScript is going to have to be in order to handle it. TypeScript is really, really good at describing JavaScript. And it turns out that most JavaScript, you really hardly need any annotations or
00:09:56 like hardly any sort of sprinkles of stuff in order for it to understand what the JavaScript is doing. So things like narrowing within functions, TypeScript is really good at understanding. Things like function parameters, TypeScript can't figure out for you, so you need to sort of do those things. But if you're doing really complicated things, like, I don't know, kind of prototype
00:10:17 assignments, or like, I don't know, messing about with the fundamental building blocks of JavaScript in order to get something done, or using maybe deprecated features of JavaScript or like the with keyword or things you maybe shouldn't be using, TypeScript isn't going to be that good at doing it. TypeScript is mostly focused on getting you working on the main path, pushing you into a sort of place
00:10:37 where actually your code is more readable because you're less incentivized to do these magical dances. So I think some people who are really, really wizards with JavaScript, they feel a little bit like TypeScript is constraining me. But I think those constraints in a team setting are good ones.
00:10:54 Kent: Yeah. I don't remember who said this, but the phrase is, tie your hands to free your mind. And I think that just describes it very well. Another person, Jared Forsyth, years ago, before I was into TypeScript, I actually got into Flow first and then later into TypeScript. But before I got into Type
00:11:14 JavaScript, Jared said, if it's hard to type, then it's probably hard to understand as well. Now, I don't know if that's always the case, because I've found that the more generic, not to borrow the term from TypeScript, but the more generic I write my code, the
00:11:35 more complicated my types have to be. And as a result, library TypeScript is often much, much harder to write because the idea of a library is to be generic. And so, why do you think that is?
00:11:51 Matt When you're writing library-type scripts, you inherently don't know what it's going to be used for. Let's say you just build a groupby function. You don't know when you build that group by function, all of the different types of objects that are gonna be passed through that, all of the different keys that might need to be grouped together. And so when you're building like your
00:12:11 library, you're essentially going, okay, this is a hole that I don't know what's going in there yet. This is a slot that needs, like the user is going to fill it with whatever they have. And that is really complicated. And a lot of type languages actually don't have a concept of that. But because JavaScript is so loose, TypeScript needs to incorporate that. And so what you get
00:12:31 are generics in TypeScript, and generics are a way of describing those little holes that you can then fill with things, and TypeScript will infer based on what you pass in to those functions. So when you're building library stuff, often you're not gonna have just 1 slot, you're gonna have maybe 4 or 5. You look at the types for something like tanstack
00:12:51 query, and there are 4 of those generic slots kind of on every single type on there, because they need to understand what data the user is fetching, and also how they might change that data via select transform. It can get really, really hairy. But I think, I mean, this is a lot of what my paid stuff is, my paid course is like trying to accomplish. It's trying to break that stuff
00:13:11 down and make it easier to understand. Because when you think of it as just you've got these little holes and little slots that you're putting types into via runtime values, then it starts to make sense and you can start to piece together the flow. But as you say, like if you're writing standard application JavaScript, often you know everything that's gonna be passed through your functions. You don't
00:13:31 need to write things in a very generic way and you don't need to care about all the possible outcomes. You might just have maybe 3 or 4 possible outcomes and TypeScript lets you be very specific about those too.
00:13:42 Kent: That makes tons of sense. And I would say also as a general rule, more generic JavaScript is also more complicated than less generic JavaScript. So like TypeScript doesn't have anything to do with it. It's just the fact of the matter. Now, it is really, really difficult to make a very generic
00:14:03 TypeScript work in a correct way. But I find that when I'm making those types of abstractions, my TypeScript is a little, what's the right word, a little more rule-breaky. Like I do things in those abstractions that I would not typically recommend
00:14:23 in product code, like casting things as any or whatever. Where like As long as I have the proper other safeguards to make up for those casts, then I feel more confident doing that. For sure.
00:14:39 Matt It's important to think of TypeScript as not a complete project yet. It's not done, you know? TypeScript isn't finished with its own type system. And so there is things inside TypeScript. In fact, there's 1 that's kind of maybe spec'd for a next version of TypeScript, which as of time of recording, this is 5.3 is going to be the next version, which might
00:15:00 improve some inference within these generic functions and mean that you're less likely to need to cast in certain situations. So currently my advice in those situations is if you have a complicated function, which is supposed to receive any kind of input, expel any kind of output, then you might need to do some casting because you might
00:15:20 know more than TypeScript in those situations. But TypeScript is getting smarter.
00:15:24 Kent: Yes, 100%. And actually, since we're on the subject of casting, I'm going to give 1 rule to folks that I think, I'm pretty sure you'll agree with me, and it's a pretty strong rule. But that rule is, well, I guess it'll take
00:15:44 some explaining. So you can make a function as a generic and you can pass in whatever type you want. And so what I have seen in the past, and I know you've seen this as well, is people will have a very generic function that, like let's say a JSON parse function, as an example,
00:16:04 and the return value of that is completely unknown. You can't really know at compile time what that type will be. And so they'll say, well, I don't wanna do a cast because that is bad, so therefore I will make it a generic. I will pass the type that the parse return type should be, and that's what the return type will be.
00:16:24 My rule is never do that, ever. That is always wrong, and the reason is that a generic to people looks like, oh, the library has considered this and will ensure that the type that's returned is correct. But in the case of something like where it's just within the
00:16:44 library function, it says as whatever type you passed in, you're lying to yourself. And lying to yourself is fine if you know that you're doing it. But by using a generic, you're lying to yourself and not knowing it. Exactly.
00:16:58 Matt Yeah. It's really easy to do that with a fetch function as well. Because you're like, okay, right. I'm fetching from an endpoint, I know what that endpoint returns, that's going to be absolutely fine. And most of the time, that's true, you don't need to validate that endpoint, you know probably what it's going to return. But someday it might break or it might do something funky. And so it's tempting to build like a, you know, a
00:17:18 generic get from end point or whatever, where you just pop in a generic slot and you, and you put that, on the end. But the thing is that fetch it's returns any. So what you're doing really is you're just hiding in any underneath a beautiful look generic signature, which, exactly the same with your Jason pass, Jason pass returns any 2. And you are just not going to have
00:17:38 a good time if that's something that you do consistently and because it looks so nice, you know, but really just hidden a bunch of stuff underneath a hidden a bunch of anys underneath a nice API.
00:17:49 Kent: Yes, yeah, 100%. And at some point, we actually, I had a conversation with Colin, creator of Zod. So that's, that's a solution right there is that If you really want to be certain of the type and it's a value that comes at runtime, then you've got to parse it at runtime. That's the solution.
00:18:09 So yeah, let's continue. Sometimes I find that TypeScript makes it more difficult to write some of my code. What should I do in those situations where, like, I know that the code works, but TypeScript is making, like, is calling out little pieces in my code that says, like, well, this
00:18:29 could be null. Like, use ref, for example. I'm passing the ref to a DOM node, and in my use effect, it will be there. I promise, it is going to be there. And TypeScript's just yelling at me. What do you do in those situations? You add the bang and say, no, this won't be null, or What do you do?
00:18:45 Matt Yeah, another 1 is like search parameters, right? It's like, you know, when you have search params coming into your application and you pretty much know that the only path that we can possibly get there, there's always going to be an ID in the search params. Why are you making me check this? What are you doing? So in those situations where you know for sure, and actually there's even, I did
00:19:05 some application work just for my friend the other day, and I was using some type generator that was sort of creating some types for me from a GraphQL endpoint. Turns out that on that GraphQL endpoint, they made everything all undefined. So it was like, okay, so like, so I know the stuff is going to be there. You know, the stuff is going to be there, but I have to do all of the
00:19:25 optional chaining to get all
00:19:27 Kent: the way through.
00:19:27 Matt And so that messes up a few things like, because you know, but so yeah, what I ended up doing is I just ended up using the bang operator a bunch. And that's absolutely fine. That's what you're saying is you're saying, okay, I know this is going to be there. I know something that TypeScript doesn't know. And you're often going to be in those situations. And part of learning TypeScript is learning
00:19:48 when you can bend the rules a little bit. Often those things are going to be just fine. And when they do go wrong, then you're going to end up with an error in your application, but you would have ended up with an error in your application if you use something like Zod to validate it anyway. So it's sometimes you just need to know when to shut the teacher up and just
00:20:08 write some code.
00:20:09 Kent: Yeah, you know, I say this all the time and people watching probably have heard this in the workshop so far, but TypeScript doesn't make your life terrible. It just shows you how terrible your life is.
00:20:23 Matt Yes. I have a sort of story about this that I was thinking about the other day. That's the perfect metaphor for this. I resealed the bath the other day, and I don't know if you have these in the US, you probably do, which is you have those guns where you sort of like put it in the sealant and then you sort of do that. So the first time I ever resealed a bath is I didn't realize that guns were a thing. So I just
00:20:43 took the thing and
00:20:44 Kent: I did
00:20:46 Matt like that. It took me about 45 minutes and I was just like, my arms were killing me at the end of it as well. I got a massive workout, but I did do it. I did manage to get there. And there was a real sense of achievement at the end. And this occurred to me that this is like how it feels when your tools aren't
00:21:07 good enough. You feel really good for having worked against your tools, but when your tools are better, it's just so much easier. And you can spend energy on different things.
00:21:18 Kent: Yeah, that's a that's a great metaphor. And like, that works really nicely, too, because it's not like you didn't gain anything out of the experience. Like, you know, you got to work out and that's, that's good. But you could have done other things that could have pushed your goals forward, you know, better. Yeah, and would I recommend it
00:21:36 Matt to anyone else? No, absolutely not.
00:21:39 Kent: It feels like the part of the TV commercial that's like, there's got to be a better way.
00:21:46 Matt Because I wasn't thinking that, you know, like as that person just doing that, writing my code or like as a JavaScript developer, I wasn't thinking there must be a better way. You know, I was quite happy with my situation.
00:21:57 Kent: Yeah, yeah, sure. So I want to add 1 other thing to our previous conversation there, where you had that GraphQL API, made everything undefined. That sounds awful. I probably would have done the same thing that you did. For the example that I gave of
00:22:17 use ref and this could be null, I actually find that, or like params as well, TypeScript doesn't know the conventions of the framework you're using. TypeScript doesn't understand use ref directly. And actually TypeScript is right. It is possible that that
00:22:37 DOM node could not be defined, or it could be null. And maybe not today, but tomorrow when your co-worker conditionally renders that element, now it is undefined or it is null. And you better believe that you're better off dealing with that problem right now than just saying, no TypeScript,
00:22:57 I know better than you. So I find myself happier adding the 1 or 2 lines of code to satisfy a condition that may not ever happen today, but certainly could happen in the future and avoid those types of problems. And additionally, you mentioned that Zod, like if you were to type
00:23:17 check it with Zod, then you're still gonna get an error. And that is certainly the case if you just parse it with Zod and then it changes in the future, you're gonna get an error either way. But the nice thing about parsing it with Zod, and I'm not saying you do this always, but the nice thing about parsing it with Zod is the error you get will be much more useful. And so it is worthwhile, like again,
00:23:37 this is TypeScript just showing you the challenges that you will face 1 day or very potentially could face in the future. And so I think it's worth putting a little bit of extra effort into listening to the teacher.
00:23:52 Matt Yes. I mean, the classic example is document.getElementById, right? If you think about document.getElementById, you know that your little app or root thing is always going to be there, right? It's always going to be there. Come hell or high water, that element is going to be there, but TypeScript thinks it might not be there. That's true, there is a future where it might not.
00:24:12 And I think in those situations, you really want to think about the error that will happen if it's not there. Because if you have like a property missing from a data structure, let's say that comes in and let's say you could have validated it with Zod. And it's just missing, right? So maybe it's just not there or whatever. Or it's an empty string or something's wrong with
00:24:32 it. And then that then flows through the entirety of your app. And it causes something like 14 levels down to error in a way that's confusing. You really want to think about the boundaries of your application and the data that's coming into it, when you have data that could be in a strange spot, and especially parts
00:24:52 where you can enter form data or things like that, or accept anything on a public API endpoints or something, like that's just gonna kill your app and it's gonna make debugging incredibly stressful when you have to dive down those 14 levels to figure out, oh, I see, we're just receiving the wrong thing. So in those situations, you just want to think about how good
00:25:12 is the error I'm going to get if I don't validate this? Because with document.geton.by.id, you're going to know straight away that something's wrong because that's going to error in the console with like this thing is not defined, right? Whereas with a Zod thing, or that element that's just not available on the data, that's going to kill you in debugging.
00:25:32 Kent: Yeah, that's a great example. I think the cool thing is that by putting forth a little bit of attention at the boundaries of your application where that data is coming in, putting a little bit of effort to validate that, and then cleaning it up so that the rest of the
00:25:52 application has really nice data and everything will result in a much better user experience too, because then you can say, oh, like I got some data from this API. And instead of showing you this janky, weird, incomplete UI, which is unreliable at this point, I'm just gonna say there was something wrong and you
00:26:12 can go and report that to your betters or whatever.
00:26:16 Matt Exactly, yeah. It just makes, and especially when you're handling errors in React and flowing things up in the right direction, you want those errors to be predictable too, so that they can hit the right error boundary and make it really nice.
00:26:27 Kent: Yeah, 100%. So Matt, You're teaching on TotalTypescript.com, teaching TypeScript wizards, making people comfortable with TypeScript and even wizards with TypeScript. So what would you say for somebody who's just getting started into learning TypeScript? Of course, we say go
00:26:47 to Total TypeScript, there's a bunch of free stuff that you can go through. But why don't you describe some of the things that beginners will go through on Total TypeScript or the things that you recommend for beginners who are getting into TypeScript and want to, or even not even beginners, but people who've been using it for a while, but just skipped over the fundamentals as part of their regular,
00:27:08 you know, cause we're developing software. We're not learning stuff just for fun. So yeah, what are some of those?
00:27:13 Matt It's like backfilling information, you know? Yeah, yeah. When you're just like, you're just working with it often and you just don't, you've got maybe questions that sort of like were buried in the back of your head 6 months ago that you never quite answered. It's so useful to get that information. And I think a lot of what I really like about your courses and what I try to emulate too is that you can skim a lot of the material.
00:27:34 You can just get a sense from the chapter headings, okay, that's an interesting little piece, a little interesting morsel, I might dig that out and then you solve a problem. And with Total Timescript, especially with beginner stuff, I try to make the beginner stuff as close to free as possible. And there's like a whole free beginner's tutorial and tons of like different articles for beginners too. And so you should definitely take
00:27:54 the beginner's tutorials. You take, especially because you're looking at React stuff in Epic web, then you should look at the free React tutorial as well, which covers all the sort of user ref and use state and all of the sort of nonsense you need to understand with TypeScript and React. And I think then too, like the TypeScript handbook is a pretty solid resource,
00:28:14 which is their official documentation. It lays out in really nice formatting and kind of order, which I think is a really important part of learning all the things you need to know to get productive and make it make sense. And I think from there, it's all about getting involved because it's 1 of the cool things about TS is that you really don't need that
00:28:34 much to get started. You need to understand how to annotate a function parameter, you need to understand the basic types, a few object types, maybe an array type, and you're good to go. You can just start being productive and start messing around with stuff. And TypeScript just comes with every front-end framework now, whether you're using Next or Remix or whatever you're using, TypeScript
00:28:54 will be an option. So it's so easy to get started and just start rolling with it.
00:29:00 Kent: Yeah, that's great. And in fact, for a lot of frameworks, it's the default option as well, because it's just, it really has 1, at least in everything that I do. That's a big part of why Epic Web is 100% TypeScript. And a few years ago, I tweeted that everything
00:29:20 that I teach will be in TypeScript unless what I'm teaching is TypeScript or like beginner JavaScript stuff. Because it just makes things so much more productive. And in particular, like you said, the typical day-to-day product stuff, you don't really need to use TypeScript that much. Like you end up annotating
00:29:41 a function and there's like, that's mostly what you're gonna be doing. Now actually on the subject of functions, I'm curious, there was a thing going around a while ago about type inference and return types and things. So yeah, there's seems to be, I think
00:30:01 we'd be remiss if we didn't touch on a couple of these hot topics. We can also talk about types versus interfaces and stuff too as this is kind of a fun subject. So where do you stand on type inference with regard to return types?
00:30:14 Matt Yep, so there's, the thing about TypeScript is you can configure it differently based on your preferences, right? So different people will have different ideas about what strict means and how strict they want TypeScript to be. And so TypeScript ships with a bunch of different config options to do all sorts of stuff. So you can have a warning
00:30:35 or an error if you forget to use a function parameter, for instance, or you forget to use a local variable, things like this. And there's 1 where you can get an error if you forget to add a return type to your functions. So you can basically say, okay, this function will return a string or number,
00:30:55 let's say. I think that particular rule in TypeScript causes more trouble than it's worth, because of a number of reasons. Firstly, it's going to sometimes be inaccurate because you can actually like type a function to say, okay, this returns string or number, whereas in fact it returns just a string or
00:31:15 returns string or undefined, whereas in fact it just returns undefined, right? So then you have to deal with the string case. So there's a lot of those little situations where you, for instance, maybe just edit the body of a function, don't edit the return type, and then like you are having to handle all that stuff further down in your app, or maybe handling the cases that aren't there.
00:31:35 And there's more to it too, if you're using like a third-party library, often the types are gonna be very, very complex. If you're using a, I don't know, like a React query or something, I keep coming back to that example, then those types you're going to need to know about the internal types of React query if you want to use them in a return type, which is really, really grim often. It's often just
00:31:55 easier if you just let the implicit stuff handle it. If you just let TypeScript handle it, and then it just flows through app beautifully. And often too, especially if you're working in a React app, your components, which are just functions, they're always gonna return the same thing, which is React.ReactNode. So why bother annotating that because you know they're gonna return
00:32:15 the same thing all the time. And so I think implicit types do have a really good set of uses, which is, oh, sorry, explicit return types have a really good set of uses, especially in like a library setting or where you're building, let's say in the utils folder of your app, where you have your custom
00:32:35 group by functions, or you have your domain functions where you're ordering and sorting and stuff. When you're working with those, you want to be sure that they're returning the right stuff because often the bodies of those functions can be very complex, and you're not quite sure what the shape of the endpoint is going to be. And it means that someone who's just scanning down your code, for instance, in a PR, can just look at it
00:32:55 and go, OK, that's supposed to return that. That seems right. And it knows that TypeScript is checking the internals as well. So I think that it's a case of whether you should turn on that rule or not, of always having to explicitly return things or not. And I think you shouldn't. I still think you should use return types when you need
00:33:15 to and when it makes sense. But I don't think you should always have to.
00:33:20 Kent: I 100% agree. It is interesting to think about rules like that being kind of like a linter. TypeScript is more than just a type checker. It also can be a linter in some cases. Yeah, that's actually a really interesting case I never really considered, where your return type can be wider than the reality. And
00:33:42 that is kind of like writing test cases that your implementation happens to support this 1 feature, but nobody needs that feature. And so then as you're refactoring that code, you have to make that test pass, but the only thing that cares about it is the test. And so delete the test. Yeah,
00:34:02 That makes tons of sense to me. So, also on, oh, there was something else I wanted to mention about that. If I remember, I'll come back to it. But yeah, I'd like to hear your take on types versus interfaces.
00:34:17 Matt Yeah. I mean, when you're talking about types versus interfaces, what we're really talking about is how you declare object types. Because in React as well, like it's essentially most of your activity in React is gonna be declaring props, right? You know, declare a type for your props and then you put that on the component. And then it means
00:34:38 whenever you use that component, you get auto-complete, you get type safety. It's lovely. And when you do that, you can either use a type or you can use an interface. And like when we're comparing type or interface normally, I think the better way to compare them is by talking
00:34:58 about interface extends or intersections. And intersections are where you can basically take 2 types and like mush them together. Use the ampersand operator and you just go, okay, these guys just get slotted together. So user and admin user are now slotted together and that's like a super admin user or whatever. And it means that they combine the types of the 2. And
00:35:19 when you do that, you are slowing TypeScript down a little bit because that is quite a complicated computation to have to do in order to understand all of the types that are going into it. And So when you use something like interface extends instead, that forces you to basically go, okay, I'm going to interface extends this thing that I was smashing
00:35:39 in. And it means that I have to give it a name. And when I give it a name, it means that TypeScript can cache it. And it means that it never needs to check that again or do that computation ever again. So when you're comparing those 2, interface is the clear winner because over the entire process of your application or like when TypeScript is checking all that stuff, it can just do
00:35:59 more caching because it knows that there are more names that it can cache against. Whereas with type, and you're doing all of these sort of ampersand mashing together, then it has to do more computation. But when we're talking about just like a simple object type, there really isn't that much difference. The thing that does maybe make
00:36:19 a slight difference is that when you have 2 interfaces with the same name, let's say, they're both called user, then TypeScript will, like if you use a type for that, type user, type user, TypeScript will complain because you've used the same name twice. You shouldn't have done that. In interfaces, you get interface user, interface user. TypeScript won't complain. It will, in fact, just
00:36:39 merge them together with what's called a declaration merge. And that is rare, But it will happen. It will happen at least once. It's happened to me. And that will be very frustrating if you're a beginner trying to understand that stuff. If you've got a 4,000 line file, if you've got 2 interfaces declared in the same scope with the same name, that's going to kill you, you know. And
00:37:00 For that reason alone, I would say when you're just declaring a simple object type, you should use type probably. But if you're doing any kind of like extends or like combining objects together, you should always use interface extends.
00:37:13 Kent: Yeah, you know, that declaration merging is both a blessing and a curse, because like there are libraries that have, they even use the term in Jest and VTest, they're expect.extend. And to be able to add these assertions to
00:37:33 that API, you have to use an interface declaration merge, like that, of course. And that's how we do it in our testing section of the course, and for adding our own custom assertions, and it works great. But yeah, that is a surprising feature. For
00:37:54 myself, I find interfaces feel like classes and types feel like objects. And so for that reason alone, I prefer types just because I don't like classes. But yeah, in general, I actually completely agree. Like you don't find yourself
00:38:14 doing really, really complicated stuff with that where you feel like, oh, this is gonna be a performance problem unless you jump into, okay, now I'm doing a library or like now I'm generating a Prisma client. And those types are really complicated. So yeah, definitely makes sense to think about
00:38:34 performance from that perspective.
00:38:36 Matt The 1 addition I would say, because that's interesting you say like app and library. I think there is a third space that we didn't really talk about, which is there's the app library, and then there's the utils folder of your app. And especially when you're migrating from JavaScript, that can often be the absolute killer. Because often, your files all across your application
00:38:56 are going to depend on maybe just a couple of functions that some guy wrote 4 years ago, and no 1 really knows how they work. And so someone coming into that, migrating that to TypeScript, you're gonna actually have to understand all that code really deeply. And probably just as we said earlier, because it's complex JavaScript, you're gonna have to use some complex TypeScript to deal with it. And the way you
00:39:17 type those functions, if you just add a few anys in them, because they're used everywhere, that's gonna really degrade.
00:39:22 Kent: Spreads everywhere.
00:39:23 Matt Spreads everywhere. And so that I think, that's an interesting distinction app and lib, but I would also add the utils folder in because that can often just make or break the entire application experience.
00:39:34 Kent: Yeah, for real. So you're telling me that it is perfectly okay, nobody's going to die if I use interface and type in the same application.
00:39:42 Matt I mean, that's often what these arguments come down to, is like, you have to choose 1. We have to be consistent. And I would just say they're both first class primitives in the language. I don't see why you have to choose 1 or the other. And I think that just rankles a lot of people and just gets them feeling like, Oh, that's stupid. Like, how could you do that in a real life? I mean,
00:40:02 you just do it. You know, I mean, you can have them in the same file. You can have them like, like they're just so similar in the way they behave, apart from just a couple of different tweaks. You don't really need to be consistent to 1 or the other.
00:40:15 Kent: I completely agree with that. I think that is the nuance that we're looking for here. Like it is okay to use both and nobody's gonna get in trouble for that. Also, I'm not your mom, so do whatever you want. Yeah, if
00:40:31 Matt you wanna use return types, you know, absolutely up to you. These are just like my opinions and from us just looking at it, I think.
00:40:37 Kent: Yeah, yeah. Well, great. So, oh, you know what? Let's do 1 more kind of interesting 1. So React comes with a built-in set of type, well, sorry, not built-in, unfortunately, maybe 1 day. But yes, there are types for React, and those types come
00:40:58 with a built-in type for a component, a function component. I never use those at all. I feel like it gives, well, okay, sometimes, like for forward ref and stuff like that, I'll use them, but for regular components, yeah, not gonna happen for me. And
00:41:18 actually, a big part of it is just I don't like, I like function declarations and you can't type those, which stinks. But that's as an aside. Yeah. So what is your take on using the component type for React components.
00:41:33 Matt Yeah, so there's a type called React.fc, which is I think the 1 you're talking about. Yes. And this 1, it really used to suck. It really used to be bad actually in like a previous version of Types React. Because when you install React and you want to use TypeScript, you install React, which is the JavaScript code, and then Types React, which is the TypeScript code. And it's in Types React
00:41:53 that this function exists. And, oh, sorry, this type helper exists. And it used to be crap for a long time because it used to implicitly add children to your types, into your props. And it meant that using it, you couldn't return things like numbers or strings from your component or undefined, let's say, which is
00:42:13 a big 1. Whereas in fact, those are now in React 18, I think. Those are perfectly valid values. Whereas, actually now, TypeScript 5.1 onwards, and any current version of TypeScript React, it's actually perfectly OK, because they fix a lot of the issues. Now, when you're using a React.fc,
00:42:34 you can actually return anything you want to, any valid React value. You can return undefined, you can return null or numbers, anything. And it won't implicitly add children anymore. So I think I don't really mind. The only annoying thing is if you need to refactor it to a generic component, let's say, then that's a little bit harder because you've got to remove the React.fc definition
00:42:54 and move it in. But so few of your components really need to be generic components that it doesn't end up mattering really at all. So yeah, I like it. I don't mind it too much.
00:43:03 Kent: Cool, cool. Something that you said made me think of this other topic. We're like a little over our time that I was planning on, but I enjoy talking with you. So, yeah. So 1 thing that I've found myself doing as I've been using TypeScript is
00:43:24 it kind of magnified something I was already doing with JavaScript. So with JavaScript, initially as I started becoming a programmer, I would read books like Clean Code and things that would say your functions should just be a couple lines long and all of these very strict rules about Clean Code.
00:43:45 So I would follow those and then over time, I just became more happy with keeping my functions longer. And doing, you know, just performing all the things. And the big benefit of that is now you don't have to do all of the boilerplate, but also like legit
00:44:07 abstraction cost of making a function. And then TypeScript comes around and it says, not only do you pay the cost of just making the function and accepting the parameters and stuff, but you also have to type all of those things. Whereas like, maybe I was able to infer that. Like a good example of this would be if I query the database with Prisma
00:44:27 and I have my select in there. So I get like all this wonderful type inference. Now, if I have this block of code, I want to move to a function, I have to accept that array of users and define their types and everything. So I'm interested in your thoughts on this, but I have pretty much just reduced the number of functions that I create,
00:44:47 and also components as well, and a large reason for that is because it's a bit of a pain. And I'm actually really happy with this. I think it's a good thing, but yeah, interested in your take.
00:45:00 Matt Yeah, I think like the ability to create temporary mess is I think a really important tool for any framework and any tool. React lets you do this. You can have components that are like 2000 lines long and you don't need to clean them up. You can clean them up if you want to, but you don't need to. And that's glorious because it just means that you can just try things out and
00:45:20 just find the abstractions when you find the right level. And you're absolutely right. Every time you create a new function, you're paying a cost there because TypeScript does force you to make, forces you to pay double duty because you have to not only find the right code to put in that function, figure out the abstraction in your head, but also you're thinking
00:45:41 about the types there too. You need to think about, okay, what things do I need to receive? What shape do I want them in? And of course you're doing that anyway, really. Like whenever you make a function, you're really thinking about all those things sort of from the get-go, or you should, and TypeScript really makes you do that too. And so I think I really
00:46:01 resonated with what you said in terms of like just allowing big functions, because often TypeScript will just help you out inside that function, just the same as if you were to capture that logic somewhere and just bring it in and pull it in. And I think that TypeScript lets us be messier because we know that we have a little bit of a cushion behind us. We can fall back
00:46:21 on something that understands our code deeply. And sure, it means that you can't use any sort of crazy abstractions or pens you in a little bit from using the stuff we talked about before, where you're really flying high with JavaScript, but it means that the basic stuff can be a little bit messier and it will still work absolutely
00:46:41 fine.
00:46:43 Kent: Very good. Cool. Well, I'm pleased with the current state of things. I'm happy with TypeScript. I think it's awesome. And Matt, I appreciate you being here to chat with me about some of the interesting aspects of TypeScript. So love to hear a little bit about ways that people can connect with
00:47:03 you. And like, I know that as I got into answering people's questions on Twitter, at some point, I kind of became interested or opinionated on how those questions come in so that I can make the most value out of them and everything. So what is the best way, now that everybody knows that you're the
00:47:23 guy who answers questions about TypeScript, what's the best way for people to ask questions to you and yeah, connect with you in general?
00:47:30 Matt That is a great question. The best place is on my Discord server, which is mattpuckott.com forward slash Discord. Not only am I answering questions there, but there's a bunch of people who, sort of like a wizard's council there, who answer people's questions. And there's some extremely talented educators in there too. So big shout out to those
00:47:50 people because they really, it's a lot of fun just seeing the questions pour in and having people, especially new people in the community answer them. And the quality of answers in there is just astonishing. So for people who don't necessarily want to be, like make it big on Twitter or anything like that, aren't interested in that stuff, like the best way I think to learn TypeScript, especially
00:48:10 the advanced stuff, is just to answer people's questions. And so having that forum there is the best place to do it. But if you really want me to answer them, then, you know, ping me on Twitter. I'm sure that's absolutely fine too. But the Discord is the canonical best place to go.
00:48:25 Kent: Very good. Awesome. Well, Matt, thank you so much and keep up all the awesome work. And yeah, we'll talk to you later.
00:48:33 Matt Same to you Kent, this was a pleasure.
00:48:35 Kent: Thank you, bye everybody!