Video Feed
TypeScript + React | Ben Ilegbodu

0
React
12.11.2020

English

Ben Ilegbodu

TypeScript is a JavaScript superset that compiles down to vanilla JavaScript and has become increasingly popular. TypeScript proponents proclaim that it eliminates entire classes of bugs that affect our applications. But what exactly are those bugs? Which ones are particular to building React components and applications? Is TypeScript worth the learning curve?
In this session geared towards devs with prior experience building React applications, let’s answer those questions. We’ll walk through the common bugs that infect our apps and learn how the use of strong types with TypeScript can help prevent them. After the session, you’ll be itching to try it out in your next project!

Transcript

Well, hello there, welcome. Up first off, I want to say happy fifth anniversary to react summit. Happy birthday and welcome to all of you to TypeScript. Plus, react equals love. You know, I kind of actually wish that I would have used a fire emoji instead, because that's how awesome I think the partnership is between typescript and react. But I stuck with the heart emoji, so I want to spend our time showing off typescript features that could prevent bugs in our react apps. OK, so I'm assuming that you have developed in react before, but you know, little to no typescript. Even if you do know lots of typescript, you'll get lots out of this. But for those that don't know, TypeScript, I'll be explain the concepts as we go. And just so you know, these slides, they're already online. If you visit my site, Ben, MVP Dotcom, you'll find a link there or you can follow the Bitly link that's at the bottom there. All right. So just to introduce myself formally, my name is Ben Aulet Biddu. I am a Christian, a husband and a father. Real quick, this is my family. That's my wife, Rasheda. We've been married ten years, just last September. That's our oldest daughter, Samoan. She is six and a half our middle daughter, Avery, who just turned four last month as well. And at the bottom is our son. He's Ashar. He's a little over a year and a half. And we're still trying to help him smile in pictures. We're still working on it. So we live in the San Francisco Bay Area, a town called Pittsburg, California. So not Pittsburgh, Pennsylvania, Pittsburgh, California, without the H. I am a principal front end engineer at Stitch Fix and I'm also a Google developer expert and Microsoft NBP both and Web technologies. All right. So enough about me. Let's dive into this react plus typescript business. So one thing I want to make clear before we begin, though, is that a react component is just a function. There's nothing really special about it. It just takes in props and returns so it can be treated in type like any other type script function. So to start off, you can use an interface to define the props as you see here. And it is the type of it becomes the type of the props argument that gets passed to the app components. So you can name the interface anything you like. I chose app props here, just for an example, but I actually tend to use just props and you will see that in following slides as we go. OK, so the first benefit, let's get right to it with typescript. Props cannot be used within a component without a definition. So like how many times have you had props in a component used without a prop type definition? Right. And in this case, we're trying to use props that loading without defining it and the props above. And that becomes an error, so there are various rules to try to catch these sort of things, but they can be limited. In fact, they're limited in how you call the prop. So similarly, when you can't, you can't pass a prop if it hasn't been defined. Right. So here we're trying to pass counts, but was it in the interface for approx? So how many times have you seen a prop been passed to a component? And it's not in the prop types and it doesn't seem to be used in the code. But you're afraid to remove it because. Because you're just not sure. Well, TypeScript gives you the confidence that you can remove it because it wouldn't have allowed it in the first place. So this error message at the bottom can seem a bit cryptic. To be honest, property count doesn't exist on type intrinsic attributes and props, but as you encounter them more and more, you'll get a little bit more familiar and used to them. OK, the next one. So react. Propp types are optional by default when you list them. So I see lots of examples where Propp types are defined actually, but none of them are marked with is required. But if you look at the code, the props are definitely required, like they're calling dot map on an array and things like that. These are bugs waiting to happen. So I script interfaces are required by default. So without doing anything special, you're guaranteed that the values will always exist. That's super nice. So if I call this component leaving off the required prop count in this case, it will yell at me and again, it won't compile. So you can use the questionmark to denote that a prop is optional, which means that its value is undefined when it's not passed. So now if I admit the count prop when rendering app in this example, there's no errors because it will be defaulted to two. OK, so if you change the name of a prop, all the places using it have to be changed as well. So let's say this prop right here highlighted was originally names, but I changed it to players within the component. So you go and you search and replace to fix all of the issues. But did you get them all? How can you be 100 percent sure? What if somebody was doing something crazy and it didn't match your regular expression? Well, TypeScript will complain if you miss a spot. And actually, a derivative of this is when you simply mistype type of prop test will complain immediately as well. OK, number four, so it looks it's a lot of work to define a deeply nested shape, right? Even with Esslin rules, we find ways to cheat. There's nothing forcing the proper types to be 100 percent accurate. Well, TypeScript is now going to get in your way and prevent you from being lazy, prevent us from being lazy. Let me put myself in there, too. But it's also saving you because you have to define exactly what's available. You can't access properties of the user unless you define exactly what they are. So if we decide in the address interface to rename is primary to just primary, we'll get typescript errors all throughout the app and the app component until we fix those. So again, TypeScript is being very beneficial in factors. OK, so the next one and this one actually is probably my favorite. So with prop types, all you get is prop types that funk for a function, right? There's nothing that tells the user of the component what parameters it'll pass when it's called or if it expects something to be returned. Right. All you get is that. Well, now and TypeScript, you have to define both the arguments as well as the return value. And once again, if we decide to add a second parameter to change, for instance, or change the types of the parameters, TypeScript will air out unless we fix all those places. This happens all the time, right. How many times have you forgotten to change a function handler in some places? Right. And the thing is about functions is that they're usually called as a result of a user interaction, meaning you're less likely to hit this error while manually testing. So now you're relying on your great test coverage to catch these errors. And we know how that goes. Right. OK, so let's take a look at an advanced pattern. Right. Sometimes you have a component and it has dependent props. So let's say you have this text component that allows you to truncate text with a truncate prop. Right. And it also has a show expand prop to provide a link, little link to click and expand the truncated text while the show expand prop. Does it really make sense without the truncate prop? So you want to make that configuration an error, right? It's much it's a much better developer experience for users of the text component, if that's the case. So exactly how do we make this possible? How do we get this error at the bottom for those of invalid configurations? Well, there are a couple of ways that you can set this up, and this here is my preferred approach. So first you define your common props, which are the props that will always exist no matter what. Right. Then next, the trunk props type is what's called a discriminating union, a fancy term, but it just means a number of objects combined together, one or the other. So then within that first is for the trunk prop for when the trunk prop is false. Or undefined, so it's not specified. So in this case, you were going to set show expand to be undefined, so that translation basically is that show expand cannot be set when truncate is false or undefined. All right, and then second is for when the truncate prop is specifically set to true and only true. So when it's turned on in this case, so expanded is an optional boolean, we're now allowed to make this extra configuration. So then props is the intersection or the combination of common props and truncate props. It's basically all of the props together. So then finally in the code, both truncate and show expanded are typed as optional boolean so you can use them as you need inside of the code and check to make sure that they exist as necessary. OK. So then let's look at another advanced pattern, let's say I've got my button component, right, that's a wrapper over HTML, an HTML button. It has some props to control the visual design at the top like variant and size. But I also want to support all of the button elements, props like being able to pass and type on, click disabled, et cetera, et cetera, et cetera. And of course, I want them all type checked. Right. So this is all about type safety. So we already do this sort of thing without Type's typescript. We pass along a whole bunch of unknown props to an underlying button element, but there is no validation and just vanilla JavaScript. So I could pass literally any prop and we're relying on runtime errors from react to tell us like, oh, wait, wait, you cannot pass an attribute to a button element and complain in the error console. Well, let's try to make this type safe instead. This is what our typescript definition could look like. Again, there are a number of different ways that we can accomplish this, but this is the way that I like to accomplish it. All right. So first you define whatever are the new props, and I'm calling it new props as interface. So in this case, this will be variant and size. These are the stuff that's on top of what a button element has. Then we want to define props that type as the intersection of new props and all of the Budden element props. Right. But there may be a chance that the button element already has a variant or size in it. So here's the catch in which case we want to override. Right, the variant and size with the ones that are in new props. But when there are name collisions and interfaces and types, weird things happen in typescript. I'm not quite sure what those are yet, but I know that they happen. So we want all of the Budden element props except the new ones that we're defining. Right. So that's what this line is doing. We use Reeves to get all of the prop names out of new props. That would be variant. That would be size. Then we remove or omit those props using the Ammit utility generic. So we remove them from the button element props. Then finally, we merged those into the new props and we have our type for our props for Butson, then finally in the component code, we can spread button props like we always do, except now button props is fully typed. It knows that type is in there on clickers in there, all of the attributes that a button has. So now the is a button. Though wouldn't be able to specify an aircraft, for instance, or some other prop that doesn't exist because that is not on the type and we would get an air. So then lastly, my last feature that I want to show you is let's say you have a list component that has a render prop for each item. But list is generic, so it doesn't know what sort of items it's getting because it doesn't really care about what items is getting, all it's doing is just displaying it and then maybe having dividers in between or something like that. It's the render that does the work of rendering the actual UI of the items. So my biggest beef with the render props in general is that I literally have no idea of what I'm getting when I'm not using TypeScript. So now with TypeScript, in this case, the list needs to be able to handle different types. So on the left we pass an array of strings and we call it length on each item. On the right we have an array of numbers and we call that to fixed on the data just to prove that we're calling different properties. So we want to be able to know the type of the item Perram in the render prop based upon the type of the items prop. Right. We have to have that relationship. And in this case, we're not typing what item is. So it's all based upon what's in items. So you can imagine if items were an array of objects, let's say, how much more necessary this sort of functionality would be. So there's how we make it happen, like I said, ORENDER is just a special function that happens to return react, but it can be typed just like any other prop function. And with the power of generics, it can be generically typed. So the list component first defines a generic parameter T. That's in the angle brackets there and then passes T over to the interface. So props of T which. And then third, it says that the items are an array of these T types, so we don't know what T is, but it's a it's a generic type. And then next, the rindo is going to be passed items of type T, so T is malleable, it can change depending on how the component is rendered. So when I render a list and pass string's T is now a string, but when I render a list and pass numbers, T is now a no. So list is generic or parameterized, as I call it. So one quick thing I want to note is that this little angle bracket comma bit, it's a little weird and not normally what you would do a generics, but the come as necessary when you define a component using arrow functions. Otherwise the parser can't tell the difference between X or an arrow function. So generics are pretty mind bending at first, as you might be feeling, if you've never seen them before, but they're also really critical and and helpful and shareable code. So I've included this link at the bottom as a resource for you, TypeScript, for generics type of generics for people who gave up on understanding generics. Pretty epic. OK, so I've got some other resources here as well for you. The most helpful one will likely be the one at the top, the react typescript cheat sheet that provides lots of recipes for common situations for you. I also only talk to about function components, but TypeScript does work for class components as well. I mean, Hooke's are the future, so you should be using functions. But if you want to use classes, some of these resources have examples for you there. So before I finish, though, I periodically host a series of short three hour remote react workshops, I call these mini shops and one of them is called TypeScript for React Developers. So if you're interested in a more hands on learning of typescript plus react doing exercises and that's such, you should check it out. Just visit my website, beinin BP dot com and you'll see them listed there. I have others as well that you see there. Zero to react with hooks, which is an intro migrating from class components to react hooks and such. So what I want to let you know though is that I am doing a free giveaway for the conference attendees to celebrate this fifth anniversary of REACT Summit. So if you go to my website again, been MVP Dotcom, go to the many shops page, find one one mini shop that you like and that you can attend and send out a tweet with the link of it. Tag me in it so I know you sent it out and I'll pick one to give a free ticket. All right. And bonus points if you can actually include a selfie of you watching this talk or during the Q&A. All right. Free giveaway there. All right. So that's it. I know I just flooded you in 20 minutes with a whole bunch of information, so hopefully you found it all insightful and it's motivated you to use typescript in your next project or maybe even in your current Riak project. That would be awesome. So, again, the slides are already available online. Visit Benepe dot com. I keep sending you there. The slides are there or you can follow that Bitly link. If you've got questions, feel free to reach out to me on Twitter at Beinin VPE and we can chat there. All right, thanks. And I hope you enjoy the rest of the conference.

Blog

Best JavaScript meetup videos from January, 2021

After our latest JavaScript meetup video selection from 2020’s finest, we’ve brought a new collectio...

Read more >>

Best Angular meetup videos from January, 2021

After publishing our Top 10 Angular videos from 2020, we’re finally back with January’s finest. Rang...

Read more >>

Top 10 TypeScript meetup videos in 2020

Ever found yourself wondering what happened in the TypeScript scene in 2020? Well, look no further, ...

Read more >>