Serverless Functions and TypeScript on Netlify
with Tomasz Łakomy
Did you know you can use TypeScript in serverless functions on Netlify with no build step? Tomasz Łakomy will show us how to get started!
Resources & Links
Captions provided by White Coat Captioning (https://whitecoatcaptioning.com/). Communication Access Realtime Translation (CART) is provided in order to facilitate communication accessibility and may not be a totally verbatim record of the proceedings.
Jason: Hello, everyone, and welcome to another episode of Learn With Jason. Today on the show we have Tomasz Lakomy. For y'all in the chat, Tomasz and I know each other because we met at -- it was JS Heroes, right? It was the first time we hung out. Then I think we really bonded in React India. React India was really a special event. The organizers did an amazing job there. We got a chance to hang out. Anyway, I'm talking a lot about you without giving you a chance to talk about you. For those of us in the chat who aren't familiar with you, do you want to maybe give us a little background on yourself?
Tomasz: Sure thing. If somebody is not familiar with me, they're not missing much. So that's fine. I'm Tomasz Lakomy, born and raised in Poland. This is where basically some of the members of my company are also based at. I'm a front-end engineer at Stedi and happy to work in a fully distributed team where all of my co-workers from my team are located in the same city.
Jason: Fully distributed team where everybody is all together. (Laughter)
Tomasz: I mean, we have 60 employees all around the world, but four of us happy to be from the same city. Everybody is in the same time zone, given the fact we live up to five kilometers from each other. Apart from that, like I said, I used to do conferences when offline conferences were a thing. I was very excited to meet you in React India. I was looking forward to having more conferences in 2020. Then offline conferences were not a thing. They are still not a thing.
Jason: They sure weren't.
Tomasz: And I'm also fairly active on Egghead, as both of us are teaching on Egghead, and I managed to record 170-ish lessons.
Jason: Holy crap.
Tomasz: Yeah, I was busy.
Jason: Dang. I mean, don't tell Joel -- Joel Hooks, who is one of the founders of Egghead. 170 is a lot. That's a solid effort.
Tomasz: Let me actually look it up. Front-end engineer. His interests include react and JQuery, of course, obviously. The master class is seven hours long. So be prepared.
Jason: Wow, that's a lot. And I'm dropping a link in the chat. These will also be in the resources to your Egghead page. So you cover a lot of things. We are not going to talk about JQuery today, which I know you're probably sad about, but we are going to talk about TypeScript and serverless functions and how to fit those two things together. So let's see what we can start with here. So let's start by talking about TypeScript. We've done a couple episodes of TypeScript on the show before. We've had Ben talk about it. We've had -- crap, I've said him name outloud before, and I forgot what his name was pronounced like. Sorry, Orta. We've done TypeScript stuff, but we haven't done a lot of TypeScript stuff. I, in my day to day -- well, I guess in my current job I don't really write code at all in my day to day. Now in and previously, I wasn't writing TypeScript often. Usually when I did, what I actually found myself doing was writing JS doc types or function returns and inputs to get, like, auto complete. But I didn't do type checking or anything. It was like, oh, let's use TypeScript for the parts I like, like the type ahead, and not deal with learning TypeScript. (Laughter) So I'd love to just kind of get your take on this. Like, you are obviously a very big proponent of TypeScript. You've done a bunch of teaching material about it. So for you, what's the draw? Why do you like TypeScript as a way to write code?
Tomasz: That's a good question. So there's a couple things here. First of all, I really care about the quality of stuff they ship. For a bunch of reasons. First of all, I believe if you have a certain amount of users, your job is to provide them with the best experience they can get. Having a page blown up in production because something apparently that is not a function is not the best kind of experience. Secondly, which I think is even more important, and you kind of touched upon this, was you have this kind of understanding -- for instance, you have a function, and you take some arguments or an object, and if you either do the JS doc thing or you write TypeScript, you always know what arguments is this function going to expect and how many arguments. How many of them are optional and whatnot. Having that, it kind of frees your mind to think about other things. You don't have to, you know, constantly look at the documentation, which you don't have because basically you don't have documentation for your internal stuff. But TypeScript serves as a documentation. Like, everything I choose in TypeScript is --
Jason: Why you got to call us out like that?
Jason: Just putting us on blast on main like that.
Tomasz: (Laughter) Oh, that's fair. But still, if you're in TypeScript, you're going to have documentation by default. And thirdly, it minimizes the feedback loop. So what I mean by that is if I factor something and TypeScript keeps complaining, like there are squiggly lines everywhere, well, I'm not going to open up my browser. I'm not going to even check because as long as TypeScript is complaining, I know this code is not going to work. But as soon as TypeScript stops complaining, then I get to open up my browser or whatever and start clicking around in the UI and whatnot.
Jason: You know, that's actually a really good point. We think about the feedback loop and shortening it, and you think oh, well, you know, I'm working locally. You get a really fast feedback loop. But there are degrees of this. You know, there's the feedback loop where every time you make a change, you have to shut down the app, recompile it, and run it again, right? Then you can see whether or not it worked. There's the feedback loop where you make a change, and then you have to refresh your browser. Then you get to see whether or not it worked. There's the feedback loop where you save your code, and it hot refreshes. That's pretty fast feedback loop. But you're talking about where you don't even have to save your code. You just write your code and your editor is automatically like, that's not going to work. It's a game of seconds, but we spend a significant amount of time in our code editors. Those seconds add up to, you know, days, weeks of effort that we won't spend every year of refreshing browsers just to see that something broken is broken.
Tomasz: Yeah, and also, it's because your cognitive resources are limited, to the best of my knowledge. So if --
Jason: To the best of my knowledge. Well, not mine, of course. (Laughter)
Tomasz: (Laughter) Oh, boy. What happens is if you work like eight hours per day as a developer and you end up switching between your editor and the browser constantly, you also switch the context of your mind because you switch from typing and editing code to clicker count in the UI mode. Going back and forth is not exactly, you know, optimal because you click around, okay, the page exploded. I'm going to go back, fix that, and so on. But one thing I would like to clarify here, because every time somebody talked about TypeScript in this kind of way that I tend to talk about TypeScript, there's always this argument about, oh, I'm not going to have bugs in production. No, you will have bugs in production. Everybody has bugs in production. But TypeScript kind of eliminates a certain class of bugs or at least makes them quite unlikely. As in, if you have a fully typed up -- you are not very likely to get -- calling a node as a function or something like that. It can happen if you're, like, I don't know dealing with something you get from the back end or whatnot that's not exactly fully typed. But it's much less likely. I like that it -- I always need to focus on other stuff, focus on things I'm actually trying to ship as opposed to dealing with those random bugs. At the cost of, of course, you know, much higher learning curve because TypeScript is not simple.
Jason: Sorry, I just got completely derailed because my past has showed up in the chat. Byron McCoy asked if I could build a website for his band, As Simple As it Seems. As some of you know, I used to be a touring musician back in the day. Byron used to be in a band we traveled with. What's up, Byron? Are you in dev these days? What's happening? No, that's amazing. I apologize for going way off topic, but wow, that's wild. Yeah, so what you just said that I find really interesting, to get my brain back into the right mode here, is -- hey, thank you for the sub.
Tomasz: Thank you for the sub.
Jason: You're talking about -- so there are bugs that happen because code is hard. You're trying to get a computer to think and thoughts are messy. You're trying to move information from point A to point B and get things to change in certain ways, and that's not always predictable. Those bugs are inevitable. You're trying to build a thought process, a logical chain. But then there are bugs where you just typoed something. You just forgot to define a thing. You're calling one property, but it's actually called something else. You know, those aren't like programming bugs. Those are typos. They're syntax errors. They're not wrong because you're thinking through something. They're wrong because you screwed up. What you're saying is that TypeScript can help eliminate a large number of those "I screwed up" bugs. Like the typos and the "I didn't realize I forgot to define that" and those sorts of things. It really can bog you down.
Tomasz: Exactly. Exactly. They slow you down. They make you less productive. It's annoying, to say the least, you know, trying to chase a bug for like five hours and then you notice it's a typo. And one more thing is that, you know, types are also somewhat a way -- because speaking of types or your example where something used to be called, I don't know, XYZ, now it's called something else. Types are also a way of teams can communicate with each other through types. So for instance, at work, where I work at Stedi as a front-end engineer, we have multiple back-end teams who are building their microservices. They publish the types for their back edges. So if I bump a version of the types and my code is full of red squiggly lines, then I know there was a change in this contract, this thing established by types. So again, I'm not likely to push this code to production, and my users are not going to complain because, you know, the page is not very likely to be immediately broken. But you are absolutely right. You may very well have bugs that are caused by your misunderstanding of business acquirements or you were trying to make the computer do this one thing and it misbehaves or it's not following your orders, basically.
Jason: Yeah, yeah. No, I love that. I love that. So, okay. TypeScript, you know, it makes sense. It sounds like it's something that it makes kind of steady improvements to save you some time, save you some --
Jason: Ah, Stedi. (Laughter) So in addition to TypeScript, we're also going to talk about serverless functions today. So let's take a second and talk about those. I mean, really, what's your story with serverless functions? What attracted you to them? What do you use them for? Why do you think they're cool?
Tomasz: So there's a number of things that I enjoy about serverless functions. First of all, they allow you to abstract a certain set of problems away, as in I have a code that I would like to run. I don't know. I'm going to send a git request. This is like one small thing I would like to build, and I have like half an hour to build that. I don't want to set up infrastructure. I don't want to think about servers. I don't want to think about, okay, I have to, you know, do all those things that kind of drive you away from the problem at hand that you want to build, like an API. Whereas, for serverless, what you tend to do is you have a code and you give it to a serverless function provider, such as Netlify. And Netlify is taking care of all of those things for you so you don't have to kind of think about, for instance, where your code actually lives. Where is that server? Well, that's why it's called serverless because you don't really know. Secondly, if you are building a side project and you've already paid $500 for a domain with zero lines of code written, then you know, your budget is probably going to be limited. With serverless, you only pay for what you use, and you know, most serverless providers have three tiers on top of that. So unless you have, you know, huge traffic, you're not going to pay much for serverless because it's cheap. And secondly, once you do have traffic, you're only going to pay for, you know, the traffic that actually gets used. So for instance, whenever somebody is going to call your function, as opposed to a server being up and running 24/7, 365 days per year. Then you have to pay to have that server up and running.
Jason: Yeah, even if the thing only gets called a few times a day. It still has to be live for 24 hours a day.
Tomasz: Exactly, yeah. If you are running like a startup and your entire customer base is in a single country or in a single time zone, you are effectively wasting money away by having this server running in the middle of the night because, face it, not many customers are hitting your, I don't know, pizza delivery website at 4:00 a.m. I mean, some do, including myself.
Jason: I was going to say, pizza delivery at 4:00 a.m. may not have been the best example. (Laughter)
Tomasz: That's a good point. I mean, some people are into sandwiches at 4:00 a.m.
Jason: That's true. Donut delivery. I learned that there are places that you can go where you can get like cookies delivered in the middle of the night, and they somehow deliver them like warm as if they're freshly baked. I'm very glad that I don't know where that service is.
Tomasz: Do they like make them on your porch?
Jason: I don't know. I think they have some kind of oven van. Or maybe it's just a trick. It's all just a trick. They put it under the hood and leave it on the engine while they drive over to your house so it's melty, not fresh. But anyway. I'm glad I don't have access to that service because I would be ordering cookies at 4:00 a.m. I would be the reason you needed 24-hour server, actually, if you were running a cookie delivery service in Portland. But I see your point. You don't want to pay for things you don't use. I think that's important when you're a huge company because little expenses add up, and suddenly you have multi ten, hundred-thousand-dollar bills, but it's really important when you're an individual. I have an idea. My idea is maybe good, but I want to see. I want to try it and find out if it's good. I shouldn't have to invest $500 or $1,000 to run a service for six months to see if people want to use it. I should be able to do it for free, right? I want to be able to validate my idea and see if anybody wants it before I have to pay money outside of my $12 or $50 or $500 for a domain. Because obviously I'm going to get the premium domain.
Tomasz: (Laughter) Exactly. Like four-letter domains which are crazy expensive.
Jason: Yeah, it gets steep in a hurry, for sure.
Tomasz: Yeah, but you're absolutely right. They also open the door to experimentation. You don't have to have a budget up front in order to start experimenting with something. Kind of the prize is a serverless service is it tends to follow your success, if you're building a startup, for instance. If you have two customers, or it's just an experiment, but when you're, I don't know, over four pizzas at 4:00 a.m. and this app explodes and has billions of customers, it's going to scale up. Also, because you're going to leverage a cloud provider underneath that. You are not going to, again, think about servers. You don't have to think about scaling them and so on up to a certain point, of course. The vast majority of all those problems are completely abstracted away from you, and you get to focus on things that are important. So making your customers happy.
Jason: Yeah, I want to build things. I don't want to like build boilerplates so I can eventually build things. I want to focus on the fun part, not on standing up the server or making sure my server doesn't, like, fall over if somebody -- if a bunch of people call it at the same time. Like, I love this idea of getting -- let's get the boilerplate out of the way. Let me just have my idea. You know, you mentioned earlier you have an idea. It's a funny idea. You want to make a little joke API. You've got 30 minutes to work on it. I am not going to spend a full weekend on a joke API if I have to stand up a node server and figure out how to get it into a docker container and figure out how to get that up on to some provider and figure out how to configure my API gateway. But if I can just put that little joke API in a serverless function and it's just deployed and I push to Git and it's live, I'll do that every day. I feel like it unlocked creativity. It unlocks my ability to just try stuff. It's not so much of an investment to have a side project when you can ship a side project in 30 minutes.
Tomasz: Exactly. Totally. Like you said, when you are starting on your project and, I don't know, it requires a database, you are halfway through an eight-hour tutorial and you forget, okay, what I was trying to build in the first place. All those things take so much time. Also, let's face it, when you are trying to build some kind of infrastructure from the very -- as a complete beginner, this is your first attempt, at some point things are going to start to break. Because you're not an expert, and your server is not a huge data center. So at some point, you won't be able to handle all of this traffic and so on. Whereas, as opposed to a cloud provider, those things can scale nearly infinitely. I mean, up to a certain point, of course, but if you're, I don't know, if a cloud provider can handle Uber or Amazon or whatever traffic, I'm sure they can handle your joke API traffic.
Jason: That's generally how I think about it, right?
Jason: At the point I need to worry about the breaking point of the cloud provider scale, if I'm not making enough money to hire an expert to scale it for me, I've made mistakes. (Laughter)
Tomasz: Exactly. Like I'm trying to imagine, how do you do that? (Laughter) How do you make a server that's so successful and you cannot -- oh, boy. No.
Jason: Yeah, right? It's one of those things. You don't want to get into premature optimization. Everything has limits, but if you assume that you're going to hit the limits of everything, then you just end up never starting.
Jason: A lot of times I see when people look at something like serverless, they'll say, oh, well, it doesn't work for this extreme edge case. It's like, okay, but you're nowhere near that extreme edge case. And between now and then, you'll have many opportunities to reassess whether you need to, like, build this on a different stack, and by the time you're making that decision, you'll have resources available, assuming your business is viable. Right?
Jason: So don't let the eventual challenges prevent you from validating the idea today. You can get 85% of the way to pretty much any business model on really affordable approaches to software. Very automatically scalable, managed for you. You don't have to be an infrastructure expert or a DevOps expert or any of those things. Just ship your idea. Get it out there. See if somebody will pay for it. Then worry about the stuff later about making it perfect.
Tomasz: Yeah, and just given the fact that you ship TypeScript to serverless functions, so it's not like a very specific way of writing code that you have to use in order to use serverless. Then if you decide you want to do something else with your code, it's not going to work. It is totally going to work. Of course, there are different ways of writing code for serverless infrastructure. This is another topic entirely, but you are absolutely right. It should not stop you from experimenting. Again, if you have a very limited budget or you don't feel like spending excess money, because why bother, you can just, you know, leverage this magic of serverless and start building stuff.
Tomasz: It's a very exciting business model. So many startups and companies and projects are going to be possible because serverless technologies are becoming more and more popular.
Tomasz: Being able to pay something a small amount of money to take all those problems away from you, and you get to focus on shipping stuff.
Jason: I love it. I love it. So speaking of shipping stuff, you want to write some code?
Jason: All right. Let's do it. I'm going to switch us over into pair programming mode here. While we're getting started, we're talking to Tomasz today. Give him a follow on the tweets. And we have live captioning today, like we do on every show. We have Rachel with us today from White Coat Captioning. She is doing -- running the captions on the home page, writing down all the silly things I say, all the smart things Tomasz says. I very much appreciate that. Thanks for being here today, Rachel. That's made possible --
Tomasz: Thank you for enduring my accent.
Jason: (Laughter) Yeah, I always forget to prep. Oh, yeah, just be ready. He's super Polish. (Laughter) No, so the captioning is made possible through our sponsors. We have Netlify, Fauna, Hasura, and Auth0 all kicking in to make the show more accessible which I very much appreciate. You can see those captions on the homepage of the site. And speaking of the homepage of the site, guess what terrible decision I made, Tomasz.
Tomasz: Um, it's something in React, not jQuery?
Jason: Okay, sick burn. But no, I went and got a toy made.
Tomasz: Ah, I saw that. It's incredible.
Jason: So there's now a Party Corgi rubber duck you can buy. Let's see. Let's get this in the middle. See this little friend?
Tomasz: It's delightful.
Jason: So I had a conversation with Chris Biscardi, who runs the Party Corgi Discord and partycorgi.com, who also just subscribed at 25 months, which is almost as long as I have been streaming. Thank you so much, Chris. But we were like, wouldn't it be cool if this thing existed? I was like, I do wish this thing existed. Like, I wished it so hard that I emailed a company and I was like, what does it take to make a rubber duck? (Laughter)
Tomasz: Okay, it's not a duck. Hear me out.
Jason: It's the rubber Corgi duck. So look at this little kitty. Here's the thing. Now I can talk to the duck whenever my code doesn't work. I'm really happy about that because I feel like it's going to save me a lot of problems. Actually, it's not going to save me any problems, but a lot of people are going to be really happy I'm talking to the Corgi duck instead of talking to them. (Laughter) So anyway, if you want one of these, they are now for sale. I've got them in the Learn With Jason store. I'm really, really happy about these, and I am intending to donate $2 of every sale to a charity. I'm going to rotate the charity and make sure that it goes to, you know -- basically, any charity that is helping people get into code. So Black Girls Code, Resilient Coders, there's some for getting kids into code, some for helping re-train folks who have lost their jobs into coding. There's some for getting people who have been released from prison. Basically, we're going to be working with different non-profits to try to get more people into STEM, and we'll do that by donating some of the proceeds from the Corgi toy. If you're into that, please get one or two or three. Maybe fill your whole bathtub with rainbow Corgis. I mean, I'm not saying I did it. But I did it.
Tomasz: I mean, yeah, you did. You did.
Jason: (Laughter) So anyway, if you want one of those, you can get them. They're at the store. I very much would love to sell a lot of these. I had to buy so many. Turns out getting a rubber duck made -- it's not hard, but you have to buy a lot of them. So please go and buy one of these ducks because otherwise my whole house is full of ducks.
Tomasz: Are they actually in your house?
Jason: No, I have a fulfillment company. I'm lying for a joke. I'm sorry.
Tomasz: Oh, okay. I was thinking behind this wall is all rubber ducks.
Jason: You know, I almost wish that was true. I could just wheel the palette in behind me and you can see this mountain of ducks I had to make. (Laughter) But yes, I'm really, really excited about that. And chat, get ready because now I'm going to talk about these all the time. I'm going to try to put together a little thermometer so we can see how much money for charity we're raising through that as well. So that'll be a fun thing.
Tomasz: I'm getting one. I mean, it's going to join this buddy that I have.
Tomasz: This is fine. He's a good friend for every single production incident that I have.
Jason: That's a very good one. Okay. So now that I've gotten through the sales pitch, right, go buy a rainbow Party Corgi duck. Please get that now. And now I'm ready to write some code. So what should I do? The first thing -- I'm going to make an assumption that I need a directory, right? So I'm going to make a new directory called serverless TypeScript. I'm going to get into it.
Tomasz: So I was thinking about how do you usually start when you do a project on Netlify?
Jason: I'm using CLI, personally.
Jason: So this is an empty folder. I just did a git init so it gets picked up by my CLI here. So I'm going to -- I mean, what? I have my Netlify server so I can run it, but let's make a directory. So to make a directory to run serverless functions out of, you create a Netlify directory. Then inside of that, we would make --
Tomasz: You have to create a function directory. Or, if I remember correctly, you can just run ntl create function, and it's going to create all of that. We can do both ways.
Jason: Oh, wait. What did I do?
Tomasz: Let me look it up.
Jason: Oh, it's the other way around. Function create. So functions create.
Jason: Here we go. Hello world. And we can call this one hello TypeScript. All right. Now I'm going to open this in my code editor over in this window. All right. In here we've got a folder --
Tomasz: I don't know why you have this on the right-hand side, but it's -- (sigh)
Jason: Look, look how nice that is. Isn't it beautiful nothing jumps? It's wonderful.
Tomasz: I would never get used to it.
Jason: You know what, I thought the same thing, and then I worked -- I was like, ugh, I don't know about this. I switched back and I was like, oh, I hate it, it jumps. So I immediately got used to it and thought I didn't.
Tomasz: It's like one of those things. It doesn't jump. It is better than the code that jumps. But I refuse to do it.
Jason: (Laughter) I refuse. But maybe. Maybe I don't refuse. I don't know. So I have this function, and this function returns hello something. Oh, so this one is like set up to do query string parameters and stuff. So let's just run it.
Jason: So I'm going to run Netlify dev. Netlify dev is definitely one of my favorite things that we have at Netlify. It makes the local development so nice. Oh, my god. Look at this. So we just ran like two commands. We were able to get -- and now we're doing local function development. So we can simplify this. Let's just -- well, how about this. We'll edit this to say chat. There we go. We're off to the races. We're building serverless functions. Oh, my goodness.
Tomasz: And this is one of the most incredible parts of Netlify. You have this entire development experience and then you ship it to the cloud. You have exactly the same experience. We can totally do this now. Let's just ship it.
Jason: So here's what I'm going to do. I have my git status. I have this Netlify folder. I'm going to git add everything. So now we have our one file we've created. I'm going to GitHub repo create. We'll make Learn With Jason serverless TypeScript. This is the GitHub CLI letting me do the -- what did I do?
Tomasz: I was saying this is the best kind of TypeScript. The serverless TypeScript.
Jason: Indeed, indeed. So we're going to create a repo here. Then I'm going to make it a public repo. Yes, please. So now we have that. I'm going to get commit, and we're going to say initial deploy. All right. Let's push. We'll set it to main. That way we can push with git push. So now it's on GitHub. I can click here, and here's our TypeScript. Great. Then I can run Netlify init. This will let us create and configure a new site. I'm going to put it on my repo. We'll call it serverless TypeScript. Okay. We don't have a build command. We're not deploying anything just yet. It auto detected the Netlify functions folder. So I hit yes. Deploy key added. All right. Then if I run Netlify open --
Tomasz: I am constantly amazed how simple this is on Netlify.
Jason: It's deploying. And it's deployed.
Tomasz: And it's going to be in production now.
Jason: So Netlify function serverless TypeScript. If I can spell it. There we go. I did something. Oh, it was hello TypeScript, not serverless TypeScript. Hello TypeScript. And there we go. We got a function. What up? All right. So now we're deployed. Any time we push to this repo, it will change. But I want to make some sweet, sweet TypeScript. So what should I do? What's my move here?
Tomasz: First of all, you have to rename the file from hello TypeScript.
Jason: Let me stop the server then because we'll be changing file names. Let me open the side bar here. I'm going to call this TypeScript.
Tomasz: On the wrong side.
Jason: I know it hurts. So now we have hello.ts.
Tomasz: So what I suggest that we can do is to make it more explicit. I think it's better if to you -- if you invite somebody to collaborate on this repo and they have this kind of knowledge, okay, what's being used in order to ship this code to production as opposed to, you know, being a hidden knowledge. So what we can do is create a Netlify.toml file.
Tomasz: Which is not named after me, apparently.
Jason: I mean, it could be.
Tomasz: So what you have to do inside is you have to specify the node bundle as esbuild. What you're going to do is square bracket thingy, functions.
Jason: Square boy function. Got it.
Tomasz: On the new line, you have to do node bundler, node, underscore, bundler. And this is equal to esbuild.
Jason: Okay. So we're doing -- we've just set a function setting, node bundler. We're going to use esbuild. This would have auto detected because we set TypeScript, but it is nicer to know exactly what's happening.
Tomasz: I think you have to indent it. The second line.
Jason: I don't think TOML cares. We can do it either way. I'm happy. You know, I'm happy if you're happy.
Tomasz: I was not aware of that. Okay. I'm used to YAML. YAML screams at you. I'm not fond of either of them. I have a thing -- TOML is okay. It's simple. If I don't have to indent, it's not the exact number of times, I'm very happy with it.
Jason: I mean, white-space sensitive languages are very confusing. Esbuild is not enabled by default. Esbuild is enabled if you use TypeScript by default. Otherwise, we use a thing called zip it and ship it, which I think is using Webpack under the hood.
Tomasz: I was looking into it the other day, and yeah, it doesn't use esbuild, but like Jason says, if you switch to TypeScript, it's going to use esbuild by default. It won't hurt to make it explicit.
Jason: Okay. So we have this thing running now. We have -- well, we don't have it running. I have a red squiggly. You told me with TypeScript, if I see a red squiggly, I shouldn't bother trying to deploy my code.
Tomasz: Yeah, so there's a number of things we can do. If we're using esbuild, we can either install types or another thing I actually recommend is to switch the syntax a little bit. Instead of doing the module export, we can just do an export from express script modules.
Tomasz: There you go.
Jason: Wait, can I run this now?
Tomasz: I mean, go ahead.
Jason: I don't see any red squigglies. Let's see what happens. I'm going to run it.
Tomasz: And that's it. This is going to run.
Jason: Hey, look at it go. And let's make a change.
Jason: Hello wow. This is now an Owen Wilson API. Wow.
Tomasz: Okay, that's it. Thanks for having me. Cheers.
Jason: (Laughter) We're done! Way ahead of schedule. Okay. So we've now -- okay. You joke, but legitimately, we did just -- like, this is a TypeScript function running in local development, and if we deploy this thing -- let's just git add everything. We want all that. So git, commit, convert to TypeScript. Then we push. Then we can come out here and look at how long this takes to deploy. Esbuild is --
Tomasz: Incredibly fast.
Jason: Ridonculous fast. With Ed Build it's going to be like milliseconds. Let's actually look at how long it takes. 745 milliseconds to bundle TypeScript in esbuild.
Jason: Just absurd. But yeah, look. Wow. (Laughter)
Tomasz: One thing I really like about this setup, notice how we didn't install the compiler.
Jason: Yeah, we didn't have to install any TypeScript stuff. I'm used to having to do a lot of work with TypeScript to, like, initialize it. You have a TS config. You have the TypeScript package. You have to install dev dependencies. You have to add a build step. So this all just works. Now, I know that it sounds like because I work at Netlify I'm pretending I don't know this stuff. I don't write TypeScript. I've never actually used this before.
Tomasz: I see.
Jason: So this is extremely cool that it just works like that.
Jason: Npm init, we'll leave that blank. Do we need an entry point? Just leave it default?
Tomasz: Yeah, that's fine.
Jason: Tomasz actually has a lot of good content on test that you should watch and learn how to write them. We're not going to do any of that today. Here our package JSON.
Tomasz: Okay. So now I suggest we actually install TypeScript. So we can do npm install. The reason we want to do this is I am kind of lazy and don't remember how to write a TS config by hand. If we do this, we won't have to. So we have TypeScript installed as a dev dependency. Now we can do npx tsc -- init.
Jason: Hey, look at it go.
Jason: Orta, there it is.
Tomasz: There you go, this one.
Jason: Yeah, this is a good episode if you want to really get in. Then we -- oops. We did another one with Ben. Where's Ben? There he is. I typoed his name. Oh, my goodness. That is bad. What have I done? Got to go fix that like right now. But yeah, Ben also did an episode with me on React and TypeScript. So if you want to really get in, you can get in.
Tomasz: Yes. So we have this. I think that we are not going to enable anymore switches. Of course, you can. You can play around with it, but it's not necessary for now. If you go back to our hello TypeScript, it starts to complain. Woo-hoo. Now can cannot ship it.
Jason: Hooray! It's complaining!
Tomasz: Yeah. Okay, so previously, before we enabled the strict mode, it used to be like, okay, this is any, but whatever, it's fine. But right now it's, hey, no, no, no. This is any. So what we have to do --
Jason: I like that it changes from like the apathetic roommate that's like, all right, man, whatever. You want to let that sit in the sink for three months, I don't mind.. now it's very much like the school headmaster. Ahem, are you sure you want to make that choice?
Tomasz: Are you sure? Are you sure you want to ship it?
Jason: Is this what you want to be? Is that how you're going to live your life?
Tomasz: I like how both of us, you know, were born and raised in a different country, and we have different roommates, but the short experience of having this roommate who refused to wash the dishes is kind of universal.
Jason: (Laughter) It really is.
Tomasz: Everybody has that.
Jason: Okay. So I'm going to just clean this up a little bit and get rid of some of the noisy bits so we can see what's happening as we start to put stuff in. I'm also going to get rid of this part and just say --
Tomasz: Let's just keep it for now.
Jason: Oh, you want to keep it. Oh, yeah, yeah. Let's keep it.
Tomasz: It's going to showcase one more feature. So right now TypeScript has no idea what an event is because we did not teach it what it is. So we can either do it by hand, which I don't want to, or we can run npm install Netlify functions, and it's going to provide us with the types.
Jason: Netlify functions incoming. Okay. We got it.
Tomasz: So this package actually exposes a number of types which are quite useful for Netlify functions. So we can -- if you do import, you know, curly brackets thing from Netlify functions, and just leave it empty. This is a handy trick I use quite often. Right now if you go to the square brackets and command space, there you go. You have all the things that are exported. You don't have to remember the names. Because I'm terrible at names.
Jason: It's this one.
Jason: All right. So let me see if I remember my TypeScript. All I need to do here is I just colon and put in handler event. Okay. Now this is no longer mad, but this is mad.
Tomasz: Yes, it's complaining but in a different way. So we are getting somewhere.
Jason: Yeah, yeah, yeah.
Tomasz: It's complaining because you may or may not have parameters. So what's happening right now is if you're trying to access a name for query string parameters, which may not exist, it's going to break. So we have to -- like the chat says, you have to add a question mark after the event, like this. And after the name. So before the name.
Jason: Hey, look how happy it is.
Jason: Let's ship it. Here we go.
Tomasz: Ship it.
Jason: Let's add everything. We're going to git commit. We'll say feature add types. So we'll push, up it goes, get into our deploys, and this is going to take a little more time because now we're going to install like npm stuff. There's some bits there. But it should still be -- I bet this is 30 seconds or so.
Tomasz: I mean, honestly, no matter how long it takes, it's much faster than buying a server, installing it.
Jason: Fair enough. Let's see how long this took. It took 19 seconds. Okay, great. And if we come back out here, still works.
Tomasz: And we can test the query parameters.
Jason: Oh, yeah.
Tomasz: You can do question mark, name, equals.
Jason: Oh, I screwed it up.
Tomasz: It's the wrong window.
Jason: Oh, (Laughter). How long would it have taken me to solve that on my own? Let's hope we never have to find out. There it is.
Tomasz: Hello, Chris.
Jason: What up? So yeah, this is great. We also know it works without because if we leave the query parameter out, we go to our default. We're not getting errors. So obviously we had to fall back in place before that was catching that because this is just like if anything goes wrong -- and we have this try catch, so if anything really blows up, it will return a 500. So we're in okay shape no matter what. But this is nice because now we're sure. We're really extra, super duper, pooper sure that this thing is going to do what we want it to do.
Tomasz: Totally. This example just had this extra catch for whatever name is not provided in the question parameters, but you may have completely forgotten about it. And it's fine because I would. I would assume whatever question parameter is going to be an empty object and I'm going to get a name from it. It's going to be undefined. But it's actually going to be known. So if you type the access name, it's going to explode. Even though we have this very fast feedback loop -- because like I said, it took us, what, 20 seconds to put this thing into production, well, still it's 20 seconds of waiting, pushing something to prod, refreshing the app. Crap, it's broken. I have to fix that over and over again. Whereas with TypeScript, it's so much faster.
Jason: Yeah. And the question in the chat about the 500. If a function has an error, it will throw kind of cryptic messages about the thing not working. So yeah, it will throw a 500. It's better to throw your own -- (Laughter) yeah, or you'll break the internet. The whole thing goes down. That's it.
Tomasz: The entire Netlify goes down.
Jason: That's it. We all go home. We just start over.
Tomasz: Jason gets a pager alert.
Jason: (Laughter) No. There's no risk. It's just a bad error. You don't get a useful error message if you don't send your own. So it's like something went wrong, and for a user, they're going to see that and be like, oh, your app sucks, as opposed to getting something useful like you didn't send in a name parameter that's required or something like that. So it's a good way to cover yourself there.
Tomasz: I saw a tweet today where basically they have this kind of feature where error messages are their features in a way. Every single time you send a request to their API, you get an error, but you exactly know what went wrong as opposed to, what, there was an internal server error. Good luck on your journey to understand what happened because we're not going to tell you.
Jason: Yeah, when you talk about the value of APIs, especially developer focused APIs, stripe is such a case study in getting that right. They're not just looking at the happy path. They're looking at when you're a developer, 90% of the development process is being a little bit wrong. Like, there's a lot of room between I've started this project and it works. So most of the time you fixed one problem and unlocked the next problem. Providing that contextual information in the error messages and showing you, you know, like, hey, you've got the API thing now, but you're not sending us the right parameter to do the next step. Or hey, you called this API completely incorrectly. You're missing this argument. Like that type of information saves me so much time versus when I work with an API that just assumes the happy path and it doesn't work and it sends 500 and then I have to go compare my example to their docs example and be like, what's different here? Why didn't this work? It's just such a power-up for a developer to have those APIs well documented, well errored.
Tomasz: Totally. Otherwise you get a 400 client server error like, okay, I did something wrong, but I have no idea. What did I do wrong? I look up in the documentation. But again, all of this could have been avoided if somebody put in a bit more work. Then again, it's incredibly difficult to get those things right. You know, my app is supposed to do X, kind of understanding all the things that could possibly go wrong. It's another thing entirely. You have to have your app in production for a year to then understand all the different ways this simple flow can be broken.
Jason: It really starts to point at the exploding complexity of building real-world apps.
Jason: It's so easy to think about one set of possibilities, but when you get to 10 or 15 different possibilities, suddenly there's this just factorial explosion of potential combinations of ways things could go wrong or be combined. Boy, does that get tricky to think about.
Jason: But yeah, I -- oh, yeah, SDKs are another example. Octokit is another example of getting it right. You know, lots of ways to get DX right and significantly more to get it wrong. (Laughter)
Tomasz: This is why we have jobs.
Jason: So looking at where we are now, right, we've shipped now a TypeScript function. It's a serverless function shipped to Netlify with TypeScript bundling. It's kind of auto deployed and up and running and everything. But so far, the only thing that we've done that feels like TypeScript is this. This is the only part that feels TypeScript to me. Everything else just looks like code. So what else am I looking at here? What else should I expect when I'm doing TypeScript serverless functions as kind of a power-up?
Tomasz: First of all, nobody really remembers what is in the event of a serverless function. So for instance, right now if you do an event, you're going to have this understanding of -- there you go. We have body, headers, whether it's base 64 encoded, whether we have query string parameters. Also, each Netlify function gets a second argument, which is called a context. So we can try to grab this argument as well. So in line three next to the event, we can do a context. We have to grab the type from -- yeah, there we go. So here we have a couple things. One, which is fairly useful, is get reminding time in milliseconds. This function over here. Each Netlify function gets up to ten seconds to execute, unless it is a bigger function, then it has like 15 minutes. This is kind of interesting to see. If you have a Netlify serverless function, which gets lots of data and processes -- or it's like running JSON stringify 20 times in a row, it's interesting to understand how much time do I have. Whether I should split the input or not. So this is one thing that can feel TypeScript-y. I was thinking we could do something a bit more advanced-ish in TypeScript. I could teach you something that is called a discriminating union, or I prefer the name a tagged union.
Jason: Tagged union. Okay. So I know what a -- well, okay. I think I know what a union is. So if I'm looking at -- like we have type cat is going to be a string. And type dog equals a string, then I could do a type pet, and a union would be cat or dog.
Tomasz: But here's the thing. If you have a function -- go ahead.
Jason: Well, let me repeat this the way I think I understand it to make sure that I know what the purpose of a union is. So if I have a type and I have a function and that function could receive one thing or it could receive another thing, I would have two different types. A union says the type is going to be one of these two. And that way I know based on -- without having to write a full superset type that has all of the different possibilities. And that doesn't even work because in one of these, like, you could have -- if it's a dog and it has a tail, then it would also need a wagging as a boolean. If it has a tail, that tail could be wagging. These need to be required. If it's a cat -- or I did this backwards. A cat wouldn't have a tail that wags because cats don't wag their tails. Then there's this whole confusing thing where like how do we specify optional based on other things inside of -- it feels like that could get really messy really fast.
Tomasz: It does.
Jason: So being able to specify, there's this type or there's this type, but it's going to be one of those.
Tomasz: Exactly. I would not be able to give a better introduction to unions if I tried. I mean, that was good. You saved me so much time. The problem is that sometimes you have a function which accepts a type, which is a union of other types. So for instance, I actually have this example in front of me, which I prepared in advance. I have a function which takes a sandwich as an argument. So we can have a type of sandwich.
Jason: Okay, sandwich.
Tomasz: The sandwich is either a pizza or a hot dog or a taco.
Jason: (Laughter) I see you woke up and chose violence today.
Tomasz: All of those are sandwiches.
Jason: Okay. So we have pizza, hot dog, and taco. All right. So we've got our three types. We've got a union.
Tomasz: A hot dog sandwich, exactly. Yeah, we can create a function. Suppose we are building an API for a restaurant. You can order a sandwich. So it's going to take -- oh, you have this co-pilot thingy.
Jason: I do have co-pilot. Sometimes it helps, and sometimes it confuses the bajeebus out of me. It's like, hey, you did this wrong. (Laughter)
Tomasz: Taco is not a sandwich!
Jason: Okay. So I think then --
Tomasz: I mean, it doesn't have to return anything for now.
Jason: Doesn't return anything. Okay.
Tomasz: Just keep it. I think the argument should be in lower case, to make it less confusing.
Jason: Oh, I thought I did put it in lower case. I think I got helped.
Tomasz: Yeah, I think the co-pilot already knew your choice. Okay, this is fine. Just accept it.
Jason: Come on! Come on! Oh, my goodness. That's amazing. Just hush your mouth, co-pilot.
Tomasz: Let's go back. Okay. So suppose -- I mean, to make it a bit more clear, let's just add one property to each. Let's make sure they're different to each type. To a pizza can have like a sauce or toppings, which could be -- okay, this is creepy.
Jason: Isn't it weird? It's creepily good.
Tomasz: Let's accept it. It's fine.
Jason: You want to use that?
Tomasz: No. Okay, we are better than the computer.
Jason: Hubris. So yeah, we can make it -- we'll say red or white.
Tomasz: Okay. A hot dog can have -- hmm.
Jason: A hot dog can be -- yeah, let's do --
Tomasz: A size?
Jason: Yeah, let's do ballpark or --
Tomasz: What's a ballpark?
Jason: I think that's the standard size. I could be wrong. I'm just making stuff up at this point.
Tomasz: A taco can be spicy or not, for instance.
Jason: Yeah, let's do spice level. Come on. Just get out with your creepiness, co-pilot.
Tomasz: At some point, this stream is just going to be you accepting co-pilot.
Jason: It's just going to be me hitting tab. So we've got three types. Each one has a unique property.
Tomasz: Yes. So I thought we should go to the serve sandwich function. We're going to have a little bit of a pickle. Right now if you do -- let's try console log sandwich.size, for instance.
Jason: Yeah, they're all -- okay. So we do size. Now it's mad.
Tomasz: Yes, now it's going to complain. Why? Because pizzas apparently don't have size. Pizzas are infinite. So what you want to do is to be able to differentiate --
Tomasz: Yes, tell the difference between the different sandwiches. What you end up doing is you add a special field to each one of those types, which kind of indicates what type of a sandwich is this. For instance, each type is going to get a field which is going to be called type with a value of pizza, hot dog, and whatnot.
Jason: So each of these, we just put in --
Tomasz: We just name them.
Jason: Okay. All right.
Tomasz: Yes. And what this is going to allow us to do, even though it may seem a little bit excessive -- like, okay, this type is pizza. Why do I have to call it a pizza? It's already a pizza. But right now if you, for instance, do -- we can do a switch statement in this function. I think this is where this shines. You do switch and sandwich.type. Right now if you have a case pizza -- this is way too simple with co-pilot.
Jason: Oh, my -- look at it go.
Tomasz: Whoa. I am impressed. What the hell? Get out of here.
Jason: I don't even know how to --
Tomasz: This is incredibly similar to the code that I pushed to GitHub to prepare for this episode. Yes.
Jason: Okay. And theoretically, this is not possible to have. This is going to return a string.
Tomasz: So there are a couple things here. The reason why we did it is if you go under the line 22 and you try to access any other property from the sandwich -- so for instance sandwich.
Jason: Oh, but look at this. I just typed dot, and it showed me sauce and type. All right. So now let's go under hot dog. Size and type.
Jason: Then I go under taco. That's -- okay. So this is kind of incredible because what we just learned here is not only is the TypeScript auto complete useful in that it picks up, all right, hey, you've got a type of taco, here are your properties, but it's contextual, too. It's picking up that it can follow this logic. We've got a sandwich. We're looking at the sandwich type. And if it's a type of pizza, then we know that it is this part of the union and none of the others.
Tomasz: Exactly. This is why it's sometimes referred to as discriminating. Because we are discriminating against tacos and hot dogs in this particular line, as in we know that it cannot be a taco. You can even see that much clearer in VS Code because if you type sandwich under the line 20, so at the very beginning of this function. Just do sandwich and hit enter. If you hover over sandwich -- so right now it's either pizza or hot dog. If you hover with your mouse, currently it is a sandwich. If you move to the case pizza, it is a pizza. It already knows it cannot be anything else.
Jason: Oh, that's so helpful. Holy crap.
Tomasz: Yeah, and if you are thinking this is neat and all, intellectually stimulating, but what's the purpose behind this? This is quite often used when you have like a server response. As if if you send a request, a request can be loading, it can be in an error state. You get a response from the server, but there was an error on the client side and whatnot. So you can model all of those with a union like this. So a result can be either loading state, error state, successful state, whatever, some other state.
Jason: And you can imagine, too, if you're looking at like HTTP status codes, like the 200 range is going to have a body, but the 500 range is going to have an error message. While they would get returned the same way as having a body, it's pretty cool that you can kind of think through it like that and say, oh, yeah, these have different components. And being really clear in the way you're communicating. Like this is what these things are for. And even beyond that, if you had -- like here's something that I think is true. Let's do like toppings is going to be a string. That can be an array. But I can add docs to this, right?
Jason: And do I just do, like -- is it one of these?
Tomasz: It's one of these.
Tomasz: It's already deprecated.
Jason: It's already deprecated. (Laughter) So I can say things like pepperoni, mushrooms.
Jason: Then for this one, like for a hot dog, let's add the same thing, but we'll say like relish, onions, et cetera. Then for this one, we'll say salsa, cheese, et cetera. So then if we come down here, what I think we'll see is if I go to sandwich and I go to toppings and I hover, it says things like pepperoni, mushrooms, et cetera.
Jason: Okay. Come down to hot dog, relish, onions, et cetera. So even if we're using the same property name, we can provide contextual hints through comments. So you said this earlier, and I think it's really sinking in how true it is. This is a communication medium. You're using TypeScript as a way to say to the devs on your team not only this is the code I wrote, but here's why this code is written this way. This is what this code does. This is what it's for. Which is really powerful.
Tomasz: Exactly. And I don't know, if somebody from the team that is managing the pizza service, they're going to deprecate the sauce or call it something else. If they update their types, it's like a way of communicating to you that, hey, your code is not going to work because your TypeScript is going to start complaining. Secondly, this is something that was also touched upon. You get to kind of think about your code or the way you want to write your code starting with types. As in, you sit down, you create all those types, and you think about, okay, what kind of objects am I going to have? What are the relations behind them? I'm going to have sandwiches. Is taco a sandwich? I'm going to post this on Twitter. There's going to be lively conversation.
Jason: So here's another thing that's really cool, right. You just said, you know, if you're managing this and you decide you're going to deprecate something, I just threw this one in here. If we deprecate the size and we say we only have one size now, so everything is now footlong. This is useful if I look at the type definition. If we do one step further and look at where it's used, it's now crossed out. It's not throwing an error. There's no red underline. This code works, but check this out. If I hover, now it shows me that it's footlong. I can see very clearly we've got, hey, this declaration was marked as deprecated. Here's my reason. I can tell you why this is gone. So now I know, hey, it's footlong. So I can be sure that that's there. Then you're saying this is going to fail if we try to compile it?
Tomasz: It's not going to fail, but what I was trying to say that it will fail at some point. Something that's deprecated will be removed. So it's an indication for you as a developer, hey, better get to it because in the next version of whatever package, this is going to get removed.
Jason: And this is great. I mean, one of the biggest challenges I think for a lot of open source packages, for example, or packages shipped at big companies is how do you communicate clearly. You're shipping a thing that's deprecated. This is 100% going to break when we ship the next major. When I was at IBM, the way we did that is we ran a code search through all of our internal repositories for usage, and then we had to go yell at each team individually to say, hey, you're still using a deprecated thing. Didn't you see my email? They would say, of course I didn't see your email. Who looks at email? We would say, but you have to look at email. That's the only way we can tell you what's changing. It was like months of getting things rolled over. Whereas, if we just ship this and they start getting an error right in line in their code, like, I'm a dev, I can read this, and I can fix this. I don't need to go read a change log. I don't need to check my email. I don't need to make sure I'm staying up to date on the change log for every internal package. I just have to read these freaking hovers. Like, that's pretty game changing, I think.
Tomasz: And this is hugely important in this fully distributed landscape we're looking into. Of course, not every company is going to be remote, but more companies are going to do remote. Having this way, this extra channel of communication between developers without going at channel in Slack, hey, by the way we've deprecated this API. Because communication is incredibly difficult. In my experience, there's no single way to communicate a change in the API. Somebody is going to miss that email, miss that Slack message, miss this sticky note on the laptop, whatever. I've tried everything. It doesn't work. One more thing that I think is going to blow your mind. What is a type of sandwich in the default case? If you scroll down --
Jason: I'm going to be so upset, aren't I?
Jason: It's a never. It's a never. That means it literally can't reach this case.
Tomasz: Yes. A never type is a type which is -- well, it's a never. This is literally not going to happen.
Jason: And you know it's not going to happen because sandwich is a tagged union, and it only accepts pizza, hot dog, and tacos. Pizza, hot dogs, and tacos are types that require this type here, and that means that this code, this is an unreachable branch unless you fundamentally change the way TypeScript works.
Tomasz: Exactly. Notice how you added this default case without even thinking about it. You knew as a developer that, okay, sandwich can be either of those types, but better save this, I suppose. I'm going to add this default case. And for the record, even though we are using TypeScript, what you usually tend to do is you add this default case and then throw an error in there. You literally throw an error, like this should not ever happen. Sometimes it's better to file early, rather than file late. If you know your code is reaching a place that it was absolutely not supposed to reach in any way whatsoever, it's better to bail out as opposed to, you know, charge for a sandwich that doesn't exist.
Jason: This is also my favorite error. This should never happen. Like, no one will ever get here.
Tomasz: How many times have you seen that in production?
Jason: (Laughter) So we'll say due to TS checks. So this is really cool, right? So what we can do then down here is we can say let's -- yeah, let's go use it. So we'll say instead of subject, we'll say type. That's going to be type. If you don't say anything, we'll default to pizza. Then what we can do is --
Tomasz: I think we could have like a small menu, so we can complete a pizza, hot dog, taco RI, just an entry from around this menu. This function is taking a sandwich as an input.
Jason: Yeah, so let's do a pizza, a hot dog, and a taco. I'm going to change this to be hot dog like that so we don't have to deal with spaces. Then I'm going to -- in here we're going to say type is pizza, and we're going to say sauce is red. Like, we'll just make that work.
Tomasz: But now it's going to complain because you did not specify the type. You started -- so you should probably do const pizza, pizza with upper case, then you started object.
Jason: Oh, I get it. I get it. So you want to do it like this.
Jason: Okay, I got you. So let's do this. Then we'll do the same thing for these two. Hot dog and then this one is going to be a hot dog. This one is going to be a taco. And -- all right. We're down to the wire here. We're going to do this fast. So we're going to set size. Our type is hot dog and size is ballpark. Before the. Thank you, auto pilot for making us fast. Taco, and spice level is -- we're going to go for spicy.
Tomasz: It's been an hour, and I'm still blown away by this autocomplete.
Jason: Oh, it's not spicy, it's hot. But it's helping me, and I could have not had to scroll up. I always forget that TypeScript will just solve my problems for me. So we've got the const here. What we will do is say sandwich equals --
Tomasz: We could just create an array of sandwiches.
Jason: Shut up. Damn it, that's terrible. But it got it right. So then we can just serve sandwich. So now when we run this, theoretically speaking, toppings is missing. Oh, let's make these all optional. And it's just like that, right?
Jason: Okay. So now it won't yell at us. Good, good, good. All right. Let's run it locally. Then let's deploy it and put a bow on this. Pizza with red sauce. Let's do type hot dog. Hot dog with ballpark size. Taco. Taco with hot spice. Okay. So we did it. We shipped a functioning piece of code, and we knew it was going to work before I ran it because we got all these pieces to plug together. We can see what's happening here, right. Like, this is really powerful stuff. So let me git add everything. We'll git commit and say add sandwiches. We'll push that. Head out to the deploys, and here we go. So this will take us about 20 seconds. Then we'll be live. Man, this is so cool. I'm so excited.
Tomasz: It's outstanding.
Jason: Let's see. Questions about databases. Yeah, there are definitely some cool -- like DynamoDB is really cool. There are some that are really cool, worth looking at. But we're not talking about that today, and unfortunately, we don't have time for the tangent. So I'm going to not go down that road. So here we go. We're now running. You can go try this right now. If you want to put in a type of taco, there's your taco. But dang, that is cool. There's a lot of potential here. There's a lot of stuff that you kind of benefit from. I like your reframing of this. It's not like you're writing TypeScript because TypeScript is the best programming language and it's going to change everything and it's going to -- you're never going to have bugs again. I like TypeScript because TypeScript is a communication tool. And I think that if you think of code as communication, which it is, you're either communicating with a computer to say, hey, computer, do this, or you're communicating with your co-workers to say this is how I solved this problem. TypeScript makes both of those loops less lossy. And lossy communication is a big problem because if I know a thing and I can describe it in a hundred words but I tell you four of them, you might get the gist of what I'm saying, and then you can go work on it. But we're not on the same page. So making communication less lossy and TypeScript being able to do that is a huge win.
Jason: Thank you for the sub, Victor. So Tomasz, what should people do next? If people want to get running, what's their next step?
Tomasz: So I do strongly recommend getting the TypeScript handbook. So TypeScript handbook is free. It's on the TypeScript documentation. The reason why I suggest it is it's essentially completely written from scratch. It's like one of the best ways to kind of understanding TypeScript. TypeScript is a large language. There's lots of it. And being able to kind of have a good understanding of the language itself will help you quite a lot when you're building and working on larger projects. Secondly, I think it's worthwhile to actually get into the weeds of TypeScript and to start small. So if you have a legacy app that was written back in 1997, probably is not the best candidate for you to start, you know, learning TypeScript. But if you have a small toy project, just give it a shot. Try replacing all the files with TS. See all those red squiggly lines and make them go away. It will become like a better, more confident developer as a result. Make the takeaway from this entire stream is notice that we shipped this entire sandwich API to prod when we were 100% sure it actually worked. We didn't do any tests. TypeScript was not complaining, and co-pilot was here with us. So we were sure we could ship it.
Jason: Absolutely. So make sure you go and follow Tomasz on Twitter. Lots of really good information there. Again, make sure you check out the Egghead as well. Egghead, I mean, Tomasz has 170 lessons on there, which is incredible. Make sure you check that out. Don't forget, you can -- I do have some courses on there. That's true. I have shipped a Party Corgi toy. Please get one. We are going to be donating some of the proceeds to chair my. So make sure you go and do that. And as always, we have had live captioning today. Rachel has been here with us the whole day, writing down all the things we say. She's from White Coat Captioning. Thank you, Rachel, so much for being here. That's made possible by Netlify, Fauna, Hasura, and Auth0. Make sure you check out the schedule as well. We have some really good stuff coming up. Next week we're going to talk to Srushtika about Ably. Ably is real-time. It is extremely cool. I haven't had a chance to play with it. I cannot wait. So make sure you come and check that one out. Then we're going to have Jamstack and headless CMS with Strapi. I had to move an episode, so we're doing three next week, Tuesday, Wednesday, Thursday. Please check that out. It's going to be so much fun. With that, I think we are finished. Tomasz, any parting words?
Tomasz: Oh, the Corgi dog immediately. I'm doing that right now.
Jason: (Laughter) all right, stay tuned. We're going to find somebody to raid. See you next time.