React with TypeScript

Oliver Zeigermann and Dave Brotherstone speaking at viennaJS in July, 2017
1830Views
 
Great talks, fired to your inbox 👌
No junk, no spam, just great talks. Unsubscribe any time.

About this talk

A short practical demo about using React and Typescript. No slides, just code.


Transcript


This talk is about Typescript and React. So, we have no slides. We show some code. We hope it works well, but most of the time, well, we'll see... My name is Oliver. I'm Oliver Zeigermann I'm @DJCordhose at Twitter, and this is Dave Brotherstone, and Dave... - [Dave] And what? I'm @bruderstein on Twitter, and I'm actually called Brotherstone, though, like, not in the list, so, yeah. - [Oliver] So, and Dave works for... - [Dave] I work for Soundcloud. And we use React and Typescript. Not on the main site, but you might have seen it on the new Xbox app. It's written with React and Typescript, and we've got another couple of apps as well that are React and Typescript. So, we do a lot of this. - [Oliver] So, I will do a short demonstration. So, as this is not at all a completely React meetup, we thought we'd give a very brief introduction of what Typescript feels like, and if you don't like type systems at all, by the way, who likes type systems? Okay, well... Maybe half of the audience. Maybe not quite half of the audience. I can actually do this, well, I thought I could. But now, I did strange things, but I think I can still do it. How is that? There you go. - [Audience Member] One more. - [Oliver] Are you serious? - [Audience Member] Yeah. - [Oliver] I need some space, man, so I don't know. - [Audience Member] Then that's fine. Keep it. That's cool. - [Oliver] How's that? - [Audience] Whoa. - [Oliver] So, you may notice, maybe you don't, because you don't see much anymore, but uh... Maybe you still notice that this almost looks like just normal Javascript file, not quite, but almost, except maybe for the weird imports of React, but this is coincidental, but it's actually a Typescript file. And you can tell by the extension. It's called TSX. And it's called TSX because it's not only a Typescript file, but it's also able to compile React. So that means the Typescript compile is actually able to compile all the React stuff that Babel also can do. That's interesting. Maybe you knew that, but, well, maybe not. So, what does it mean? So, even if you don't like type systems, well, half of you don't, maybe there's still benefits like you don't write types, but you let the Typescript compiler unfurl the types for you. And it's a little bit like linting on steroids, like very strong linting, like type-based linting. Let's say I have a string, just a string. And this is just... Doesn't matter. There's something wrong with my keyboard now. That's really weird. How is that possible? Oh, there you go, okay. So it's just a string. It doesn't matter what it contains. You just see it's a string, right? But you don't see type annotations, or do you? Well, I don't because there are none. But then if I do something wrong, and I'm totally aware that this is a very silly mistake, but just to make a point, I'll just put it in here. We'll try... I will eventually use co-completion. There you go. And then, down here, you see an arrow, like immediately. So, this is, by the way, Pusher studio code, so it's not like one of the fancy, pricey IDs. But it's just like a random ID, you see an error message. And the same error message you see here when you hover over the red thing here. And it tells you: Argument of type '"huhu"' is not assignable to parameter of type ReactElement. So because this is Typescript file, and because it knows React actually expects ReactElement, which is very reasonable, it is not okay with the string, with a special content of who, so it tells you, "No, I'm not going to do it. It doesn't make any sense." And as you can see, I haven't written any type annotations yet, so that's quite nice, right? At least for me, it's quite nice. Who likes that? I mean, anyone? Please raise your hands. It doesn't matter if you like it, just raise your hands. - [Dave] We're going to carry on anyway. - [Oliver] Right. So, well, you may like it, but there's more, of course. I mean, this is really simple. You could actually add type annotations if you are so inclined, and if you like that. Then you can put in, that's a string, and then types we'll go for sure. Okay this is a string. So we don't mean it to be like that specific string. It can be any string. Why would you do that? I mean, the first thing was like linting, but the second thing is documentation. So of course, this string is called, just a string, so adding documentation of that this is a string becomes a bit silly. But it's an example. So everyone now looks at this variable knows it's a string. There's documentation. It's silly for this example, but it might not be so silly for other examples, like if you look at a little bit of React code, that's really huge now. But anyway, so say we have one component here, and this component will be like, a controller thing, that sort of like wraps other components, and then use the component, and then you may wanna know like, what can I actually pass it in? So first of all, if I erase this, it tells me, that's all good, there's something missing. You're supposed to put something else in, so if I hover over this, it tells me, I mean, somewhere it tells me, that it's missing greetings. So that should be greetings. So what can I do about that? So I start typing, and then it tells me, okay, so I have three things, then it also tells me, wait, it should tell me, hopefully. It's a little bit tiny, but it should tell me, in a sense, like what type it is. It's a type of greeting array. So it's an array of greetings. And that's also common, that added to the types of decoration, it tells me it's an array of greetings to this play. Well, it's not a good comment, but at least it is one, so. Before I type the greetings in, I replace all this, so I get something like, documentation a little bit, I get co-completion, I get reasonable reasonable documentation, if I'd actually written reasonable documentation. And then I can navigate around, like this. So I can do that. Why isn't it working? So it's strange for me today. So typically I should be able to just right click, it's not a good day for me today, as it seems. So typically this does work, I don't know why it doesn't work today, but now, it doesn't work, maybe it works for this one. Also not. It's a bit silly. I'm sorry. The importer or code all compacts, so it's just, I don't know, maybe too many reboots. You never know, Let's try something else. So typically what would have happened, I click on this, I navigate it to a greeting master, I'm doing not many of them, and what I often need to do, especially when the application becomes larger, I hope this works now, is that I need to rename things, like, I got the impression that 'Greetings' maybe is not a perfect name. I'd rather call this 'GreetingArray'. I'm a little bit afraid now, because things didn't work a second ago. So I change this but I can also check it here, where it is used, you didn't see this, but this was called 'Greetings' a second ago, and then I can also check how this works, I can also hope this original file, and you see that the refracting also did work. And Well and you may not be too enthusiastic about it. I've tried my fair share of refracting JavaScript and never worked on me. So and there are some people who actually, like smarter people than me, claim that it's actually not possible to reliably refract a JavaScript, without type annotations. And one last thing before I pass it over to Dave, I think I'm pretty good in the timing, there is one more interesting thing, so lets say you'll be interested, but you don't have the Typescript project yet, all you have is JavaScript files, you may notice that one of my components, like this one, which unfortunately I can't navigate till now, is not a Typescript file, this one, you'll see it on this side, but it's actually JavaScript. So it's just a random JavaScript file. And I can equally just use it. So it has the same imports to make it a little bit easier for Dave, in a second, but other than that, it's not even a Typescript file. But you can still use it, from within the Typescript component. And if you are at all familiar with Typescript, I will show you how this is possible. If not, you can look somewhere else, for a second. So there's a configuration file, for the types of compiler, and we make it really strict, whatever that means, it means good things, and then we allow Javascript to be included as well. We could also turn on type checking for JavaScript, but this will cause a lot of arrows. Okay, so you turned it off. So this is like the typical way. I turn it off until it gets to a reasonable amount of arrows. So what Dave is going to do now, is turn this JavaScript file, into Typescript, are you ready for this Dave? - [Dave] Cant wait. - [Oliver] Okay, I'll pass it to Dave I'll be right next to you. - [Dave] Thanks. Yeah, so the first thing we're gonna do is, wow this is huge, - [Oliver] They made me do this. - [Dave] We're gonna rename the file obviously to a dot tsx. Yeah, doesn't work there, it's gotta be down here. - [Oliver] Right. - [Dave] It's not my editor, it's not my laptop, it's not my keyboard. Those are my excuses. Okay so now we've got some problems down here, it says 'generic type component' PS requires 2 type arguments. So this is because Typescript has generics, and one of the key things that React uses, obviously is props and state, and you can type the props and state, so we're gonna do that, and we're just gonna define it as undefined for now, so that first one is props, and then states. So we're just gonna say it's undefined. Which is gonna be fine until we actually try and use the state here, we can see undefined doesn't obviously have a name property or a greeting property. So let's define that, let's define the state type. So we're just gonna define it interface, Not yet. I mean, doesn't matter. Any wouldn't give us an error though. Yeah. Yeah, we want the errors. The errors are good. Cause the errors show us where our problems are. So we're gonna fix the errors. And then we'll end up with a typed file, if we do it the other way around and say 'any' then it'll just say 'yeah it's all good.' And we'll go, okay what do we need to fix then? We haven't won anything, other than just converting it to type. - [Oliver] So just a matter of fact, like setting the strict mode, actually is like never infer any at all, and once I write 'any', like explicitly, anyway my code is like defeat, so we will experience defeat a little bit later, not me, fortunately, but Dave. - [Dave] So name and greeting were the two. So now yeah we need to put it in the thing, I just can't see it, the fonts so big, - [Oliver] Just by the way, if you see this angle bracket thing, and you don't know what it means, jut no worries, you don't have to . You just put in the state there, and the props you put in the other place. - [Dave] So that's made the first error go away for state, that's fine now. So now let's do the props. So we can basically use these prop types, and we can just convert them to types. Types are better because we'll get it in the editor, and not at run time. And it doesn't cost us anything at run time. It doesn't add anything to the bundle, we don't need to strip anything out, or anything like that. What was it? Greeting might be 1, and it's a greeting. No it's a it's got a name, hang on, I can't see it all. How can I get rid of this bottom thing? - [Oliver] Can't you use greeting and then do the fancy... - [Dave] I don't know, I don't know, I've not tried it. So we can just define a type within a type, that's fine. So it's got a name, and that's a string, and it's got a greeting, and this is also a string. You didn't show them, did you show them the app? - [Oliver] Sorry? - [Dave] You didn't show them the app, did you? - [Oliver] Oh, I did not. - [Dave] No. - [Oliver] I'm very sorry. - [Dave] Do you wanna see the app? Do you wanna see what this does? Do we care? It does that. It's good innit. And this component is actually the component that does an ad. So you've got some state on you can enter a name, and you can enter a greeting, and you can save it. And it's built so that you can write, edit, but you can't edit it in the app yet. There we go. Oh we've got 'onSave' as well. onSave is a function, and onSave takes out, this is another thing that we can actually define what onSave takes, so if we say it's empty, now it's just a function. Ah I'm in German. - [Oliver] It's in German. - [Dave] Speaks German) So onSave is a function that returns void. That's all we know. And we'll see in a moment, that it's later on, somewhere down here I think, somewhere down here, yeah save, it's like, save does not fit, it doesn't take this name in the greeting. So we can actually say, - [Oliver] Yes. - [Dave] Yeah, so. - [Oliver] So it's no different here. - [Dave] Oh yeah true. Good point. So let's put that in. Let's go through, and alright, we'll take the prop types out, and we'll fix the other bits as we hit them. So the next bit is, we've got a ref here, the ref is unreliably informed, so that you can set the focus on the import, if you clear. So we need a property. Visual Studios does this really well. You can just say, command dot and here you can totally read this, it says 'add declaration for missing property import', you hit enter and it knows what it is, and it just adds the property and now this is fine. - [Oliver] Do you like this? - [Dave] And also, - [Oliver] Just raise you hand - [Dave] And also, if you do this dot import, you get property completion. And you can see everything that you can do on html imports, so that's quite nice. Now we're gonna get the proper error. Oh, yeah it can't infer the props type from the, in the constructor, and it's just the Typescript limitation you just have to define it again, if you're gonna use them here. Somewhere I think, save is, yes it is. So save is gonna, is erroring now, is saying we can't pass the name and a greeting to save, because we've not, we've defined it but it doesn't take any parameters. So this is kind of a win over, what you get with prop types. So here we can say is it greeting and then new greeting or something? Ah okay, Cause I've not imported it, so again command dot, you can't read that, it says import new greeting from types. And it imports it, with double quotes. Webstorm does the exact same thing, but you can customise it in Webstorm. Just saying. I think, now you can customise that too. Yeah, you can. - [Oliver] But you cannot, maybe you open up the prop type again, and see if there's something left. - [Dave] Oh yeah, there is one thing here that the event isn't, so this is the event that's on the click, that we call in, sorry, not on the click, on the change of the two fields, and this is doing an evil thing, it's saying set state, and then using the target name, as the key, and the value, and just updating the state. So first of all we need to set the type of the even, now we can go up here, where we assign it. These functions are in a really weird order. Further up here. We can say input is, oh yeah, it's here, right, just here it says React dot change event html import element. So it's a change event, that is, cause React obviously use synthetic events, so the synthetic events are then wrapped so you don't get the native event type. So it's a React dot change event html import element. There it is. And then it says yeah, but we can't just se the state to this because, the problem is, that I can do, it's actually really smart with this set state, it saves one of the common things that I do all the time, is like if you do then it actually says, no you can't do that, because you've not got that defined on your type, but that's fine. But obviously it doesn't know here that actually we're only ever gonna be called from something with a name that has a property in the state, like it's not that clever, it's not a genius. Now we sat for, what was it, two three minutes this morning, - [Oliver] It was. - [Dave] Yeah it was, yeah we sat for a very long time and tried to get this typed. And we went round and round in circles, down the rabbit hole, out the other side, and that is what we came up with. As any, sorry as any, yeah. Yeah, so I think Typescript failed on that. I don't think we failed. - [Oliver] So as I said, every time I type any, it's like defeat, because you don't want to invest all your time into writing type annotations, because why would anyone pay you for that? But then you want type annotations, so writing any is like okay, we spent a reasonable amount of time, trying to figure it out, we are not smart enough, or it's broken or whatever, so we type any. And any is like disabling type checking for the whole expression that any is useless. That means like switching off type checking at this specific point. - [Dave] But it does have, like, if you're reasonably pragmatic about it, there are cases, obviously where you can say right okay, I don't want to type check this part of the this function or this method or whatever. Because sometimes you just can't. There are cases where, you're trying to write a library, and you might get something in, and you yeah. There are various cases, we've got a few libraries that like are type checked, but in order to actually implement the internals, we have to just 'any' somewhere. There's a couple of cases that we use in Redux for this as well. Cause Redux, the typing is really really good. And you can get things like warnings if you don't handle every possible action that you're supposed to handle. Even if you use the wrong constants, or if the strings aren't right, cause you can actually, a string has a type, so you can have value types in Typescript. So you can say, that the type property of the action, must be add greeting, or delete greeting. Literally, in quotes. So that's really neat. - [Oliver] So obviously what Dave is saying is that it's perfect for Redux as well. But we don't have the time to explain it. So I think it's very hard to just understand it by not looking at code, so I think we're out of time Dave. - [Dave] We've got one second left. I normally talk about unexpected react, please try it, - [Oliver] What is it? - [Dave] It's a testing library for React. - [Oliver] Do you use it? - [Dave] Yes, as does them. - [Oliver] Okay, so out of time. Thanks a lot. Is there time for questions?