hi hello everybody and welcome to my talk Lies We Tell ourselves using typescript so if you can see this um it means that I'm sadly not able to be with you live in person to talk to your life but believe me I'm with you uh in my mind and hopefully in the chat um and I still want to give you a great experience with this talk even if it's from the can so let's get going um and the best way to do that is by saying hey I'm I'm sorry I'm very sorry you have seen probably a lot of fantastic talks today I've seen the lineup it's brilliant it's actually people that I I long for to meet in real life again um and now it's my talk and I will crush your hopes I will destroy your dreams and I'm very sorry about that so I'm talking about types script and I talk a lot about typescript so it's um I've written two books in typescript typescript in fifth the lessons your guide two through the type system and the typescript cookbook U which is here for teams who want to develop a typescript and you know have have problems getting everything up and running might have problems dealing with certain type system situations um so yeah I spent a great deal and a lot of time with the programming language and I I like it it's it's a great programming language uh look at this piece of code for example this is the example I us usually bring um when I want to people to convince typescript is a great idea um it's 10 lines of code or 15 lines of code and there are more than 10 errors hidden throughout the entire um um program um it's not the best program but it's you know maybe a program that you and I would have written back in our days uh still it's programs that happen and nothing in this program would have caused a crash nothing would have caused a runtime error it would have just run and it wouldn't have produced any meaningful results and those types of errors are really really hard to catch and typescript helps us catching those things so fantastic this is what we are here for this is actually great but I'm not talking about this today I'm talking about the total opposite look at this piece of code some typescript code is very well typed it's complete it compiles it runs and it might throw errors at runtime actually it might throw a lot of Errors at runtime you know those kinds of Errors typescript is supposed to prevent and it's just two functions one fetches data and the other concatenates the results to an existing array um passing it right off the bed might be a bit much so let's go through it step by step first we have some function overloads define an API to the outside world that tells us exactly what to expect if we call species or people function overloads are a fantastic way of doing nice and easy to use apis then we have the core of the first function we fetch some data from the Star Wars API or swapa if you have heard about that it's a great online resource to test restful apis um and it also comes along with some meta information we are not interested about the meta information so we just return the results um uh of this function call um and yeah we also have some error handling in case something goes wrong when passing the Json and in the end we have a simple function that takes two array in concatenates them finally we using it we Define an empty list and imped data to it VI call to list entries two functions one fetches data and the other one concatenates the results to an existing array that's pretty much a standard types script fair and you know again it might not be the best program that there is lots of stuff that might go wrong um but you know it's code that you and I would have written and typescript is totally okay with everything uh that happens here but what could go wrong and I think everything actually there's not a single line in this Cod piece that's actually not causing any troubles so where does it go wrong everywhere and you know how does it go wrong well one by one because typescript is single threaded and that brings me to my most favorite JavaScript joke knock knock race condition who's there anyhow let's go through all those problems so welcome to chapter one A Tale of Fetch and let's look at the core of this particular statement there's one damn lie hidden in the first line directly after the fun signature well actually headline three I'm sorry um I'm doing a type annotation I say that what comes back from the result. Jason call is of title mattera of people and this line only works and typescript allows this line only because the chasing method from the body interface returns any and any is the happy type in typescript everything's possible um and if I say data is matter of people then typescript says yeah well okay whatever you know best it's any it can be anything it gives the respons ability to you the developer to make sure that the data that you assign is actually correct and this causes for the first boom so if anything anything comes back there that isn't met of people this program will crash and what we see here is typescript at its boundaries where the meta world of your types that nicely and neatly fit together crashes with reality uh and you know the type system of typescript is frag at the boundaries which is mostly IO API calls user input you name it everything where you need to read something from the untyped world going into typescript and this is where you need to make extra checks to make sure that whatever happens is actually what you intend to happen and you know there are two kind of things there are type annotations we've seen that but there also type assertions and I'd like to call those type assertions to be an unsafe operation Operation that is at the boundary between your idea of what needs to happen and what the type system is actually able to ensure and those things actually happen quite a lot in typescript so let's look at a couple of those indicators for unsafe operations we have as for a type assertion it's for type predicates um sorry is for type predicates and asserts X for assertion signatures all those keywords tell us that something is a foot in the type system they show us potenti potential breaks because they assume certain types are dependent on what's happening in JavaScript and typescript can't figure out those things are correct so if you look at the isce function here we tell it that you know if the number we get in is in the array of one to six is one of those six numbers then well dice is a dice so if this evaluates to true then we can make sure that the number is actually a much much smaller set of numbers and of type dice but we could as easily return true in there well anything else it doesn't matter as long as it evaluates to Boolean so it's just good as good as our programming but one thing is important about this that we spot those anfe operations through a keyword as or is so if you look at those two lines they basically do the same line one is a type annotation we say well we are waiting result of Chas and whatever comes back should be of type met people and the second line says well whatever we get back here we want to treat as matter of people um and and you know here we explicitly tell typescript you know from that point on I know better than you this should be meta people um and ask yourself if you are in a huge code base which one of those two things can you spot more easily I'd argue the last one because type annotations happen everywhere even even if you have proper type checks happening but those ass type assertions you know those little pushes of the type system where you say this is how it's supposed to be right now um you can do a text search for that and see oh wait there's an answer of operation maybe there's something is wrong I need to be aware that something here is happening and the good thing is is that we can enforce those type assertions we can say well let's open up the interface body and rewrite how the Chason method should behave so this is called declaration merging interfaces in typescript are never Cru so you can always extend them you can always throw the method Methods at them by simply red declaring the same interface all previous declarations are still valid you just add to the bottom you have method signatures that are basically the same but one is any and the other one is unknown well then the unknown one counts more um and when I do that when I open up GL and then the interface body again and then I say well this is now a promise of unknown this line here will fail because typescript will tell me that unknown is not assignable to met people um in in this particular line and and unknown is made for this so unknown allows the same set of values that any does but unknown is cautious it's the cautious sibling of any and he tells you well at this point you need to make sure that the types are correct and you can do that by either you're narrowing it down with your usual means or by just saying well let's moove the type an notation and see as met the people it does the same thing but it becomes more visible that something is going WR all right first problem first solution next one the theme is dark and full of Errors um let's look at this particular catch Clause it's very interesting and I'm very curious on what what has happened here so this is something that comes from a real world project that I had to review um and and you know I ask myself what what were you thinking what is going on there it's actually one of those lines where you couldn't quite spot what's going on so the developer did actually something nice they knew that res Chason could cause a syntax error if if what you return doesn't be it doesn't this actual any real Chasin but something different so you're getting a syntax here which means that you hop into a catch CLA and the way I handle this catch CLA it's bogus so you can do much much better things there but but look at the type signature why are they calling for a synx error or any and the reason why they do that is that in JavaScript everything can throw everything you can throw errors you can throw objects you can throw the number two all is fine JavaScript is actually little bit like my three-year-old son my son throws unexpected tantrums and I have no clue what's going on and JavaScript is throwing unexpected errors and I have no clue what's going on um but you know that's actually a feature of this this dynamically typed language um if a type error happens or if some a synchronicity error happens or if some syntax error happens anywhere in your code that's being parsed lazily then this stuff can error and you get those undefined is not a function calls you get those type error calls you have seen that in your in your console in dep tools you have seen those things this happens because in JavaScript anything can break um this is why typescript won't allow you to narrow down four very specific errors it's a false assumption in typescript to say you're catching for one particular error for the syntax error because there's so many potential problems happening in the code above and also other errors that could occur this is why somebody snuck in a little any so the code says well it's a syntax error or it's any and that's the truest representation of what's going on here because well either it's a syntax eror yes from r. Jason or it can be anything because it's JavaScript but if you add any in a union with any other type the whole type becomes any which allows you to access every property aaable this the this code didn't blow up at runtime is mere chance and in typescript we are not here for chance we actually want to know what's going on the only mitigation for that is again going for unknown in catch Clauses and doing instance of checks so if we activate the use unknown in catch variables flag in the T config chasing your e becomes Unknown by default you can't put it in a unit because it stays unknown um and and you would have to explicitly add any to to make that work um so let's keep it with unknown you can't do anything with the tab before you don't do any instance of checks like well if it's an instance of syntax error then you can do proper error handling and again the error handling here is bogus maybe if it's a syntax error let's return a real error message and exit the whole thing um otherwise maybe return an empty array so so it totally depends on the semantics of your application okay second problem second solution let's go into the next problem and this is maybe one of my favorites the metrics overloaded you know I want to turn your eye to the function overloads personally I'm a huge fan of function overloads because they allow you to design apis like this they tell me that I get species for the key species for the literal string species and I get people for the literal string people this is what the two function signatures at the top tell me and then I have the implementation signature I get species with species I get people with people but in the code I only return people so again in in the signature it tells me I get species but in the code I only return people so in the signature it tells me I get speces but in the code I only return people what's going on here and this is one of the biggest carats in function overloading um so those are all the function signatures that we have and let's see what they mean let's pull them AP part A little I have two function signatures that expose the usage API this is on the top um this is what you see when you actually call the function and the other one the one right before the function body is the implementation signature this signature is hidden when you call the function this is just here for you to actually Implement stuff in typescript there's a couple of type checks the first type check that it does is that all the usage signatures are somehow mirrored by the implementation signature you so you can't defined anything in the usage signatures that isn't defined or capable of being called in the implementation signature this is why a lot of them are trust defaulting 20 any which is a very bad idea but that's what's happening here um and the other type check that's happening is that if you are doing uh an implementation in the body it checks if everything that you return actually is valid against the implementation signature and the problem is that nobody tells you that everything that you covered in your overloads is actually being covered in the body because the check goes usage to implementation and implementation to body but not usage to body this is not happening so nothing absolutely nothing keeps you from returning absolute bull trip that doesn't make any sense at all um you can say well oh it's if if kind is species then return people and if kindest people then return species you can do that because the implementation signature says well that's valid you can do that but the usage signatures tell you something entirely different and nothing absolutely nothing in typescript is preventing you from doing wrong to this data one possible medication are conditional types with them you can offer the same type of parameters in return types as overloads but since they are complex typescript can't figure out what you're returning is actually what you're supposed to be returning like here so this is um this is um um I'm doing here type assertion where I assert that it's metap people of species because otherwise types could script would not allow me to do anything I would get an error and it would tell me that people or species are not designable to type return of T so you would need to do another type assertion here as well you would need to act you see an unfe operation you know that if something something would be problematic it would be here again we are not only here to see if typescript has a sound idea of what's going on in the application but also if you can spot the problems that typescript goes wrong one more last one the unexpected virtue of ignorance if you know what movie this is tell me afterwards in the chat um and this is arguably one of my very favorites because it's so simple yet so painful um and we ured a lot of pain already didn't we so in in the second function I have a function called append entries append entries takes a list of people of species and you concatenate them with another list of people or species fair enough since the paral list uh is passed per reference it mutates the list but look at the actual usage I create a list of people and I append entries of type species so the type of list before I call aend entries is people and what's the type after I call pend entries sorry here what's the type of list after I call P entries it's still people it is still people and you know the reason for that is that all the contracts for typescript are fulfilled you are getting people in there and you're getting species in there and the function accepts people or species so well the types check out everything is okay but the problem is the typescript can't react to object mutations that happen if you pass something along by reference which you can argue is actually a problem of JavaScript itself but still it's something that we need to deal with and one thing that you can do how you can deal with it is by adding generics so in generics you instead instead of the broad type that you have here of a r people species you add a generic parameter of the same type so you say well whatever we put in there is a subset of people or species array um and then you set the list and from to the same type and the moment you call this function typescript locks t to the concrete type of the first parameter and tells you that you can't mix in merch is use it fit now you need to act so here it says well the argument of type promise species is not assignable to the parameter of promised people because with adding list at the first parameter T becomes array of people and because of that from or needs to be of promised people all right everything mitigated four problems four Sol Solutions let's enter the Final Chapter lies damn lies and typescript so the story so far we found four medications to four problems we used declaration merging to patch assumptions used here as reset by mat pook it's a fantastic Library doing exactly that um you are doing instance of checks and unknown in catch cses to work with aot types you use conditional types instead of function overload to provide a similar API and highlight unsafe operations and last but not least you have generics to allow you to narrow down to specifics to make those type parameters concrete with usage so far so good more lies more damn lies every solution that I told you just comes with more damn lies here declaration mer I declare an interface that is called form data and the moment I use it in handle form I can access apis that I haven't defined where are those apis coming from from it's because form data already exists as a global type and then merge with a global type so declaration merging is fun until you accidentally merge with globals and say don't say this is artificial I know so many people who had exact this problem and that's why this is my favorite undoubtedly so um instance of checks hooray um I have two classes Class A and Class B both have a very distinct property Class A has the property a Class B has the property B then I have a do something function that accepts both A or B as parameters to access the correct properties I do instance objects to get the right type in the control flow so after P instance of a typescript knows that P is definitely 100% of type a right right um but hey typescript is a structural type system which means that I can just pass Elements which have the same shape as a and this will compile but but you know it's just of the same shape of a it's not an instance of a so JavaScript only allows the instance of check to happen if you actually constructed a class with new not if you pass something that looks and feels like a so typescript allows that JavaScript instance objects don't but typescript instance objects narrows it down to the wrong type which means that in the else Branch I would access B which isn't there it would be undefined because I have a of 42 okay this will cause this function to lock undefined but you know think about you know calling this parameter times two or something you will get an eror at run time so yeah instance objects are great Until you realize that typescript is structurally typed conditional types yeah I'm sorry anybody knows what's going on there I I don't um and I should because I I've written this this February and I've even a five-page explanation and I booked the typescript cookbook and I couldn't tell you what's going on there um so so conditional types are powerful they are incredibly powerful but you know it's like from the creators of regular Expressions comes the sequel nobody want it they are complex and you really need to think about if you want to add this kind of complexity to your code base so they are hard to pass they are hard to write the required documentation use them wisely or don't use them at all ask yourself if the complexity is worth the benefits that's all I'm saying here and last but not least generics generics are great but they can be explicitly annotated and then you have the same problem as before so be aware the generics are a solution and a very great solution so I use them a lot but they are not theu and with that all of our Solutions debunked again more problems more solutions more problems let's go to the end again I'm sorry this was not a nice talk I hope I didn't crush your hopes or destroy your dreams uh you are here to learn something to get excited about typescript about JavaScript you have seen so many great speakers and I adore all of them they are fantastic and now you hear a crumpy 40 something talking about stuff that goes wrong with his computer um and you might ask yourself so after all of that I've written two books on typescript I've given countless talks on typescript what what do I think of typescript well I love typescript it's still the second best language I have the pleasure to work with and I wouldn't want to work without it seriously typescript is actually not about a sound type system it's about making you productive and I just can't argue with the fact that typescript makes me tremendously productive and you know what this title is not called The Lies typescript tells us it's called The Lies that we tell ourselves as developers and there are a couple of Lies there lies that well our type system should be sound that's a lie we tell ourselves when we use typescript um and another Li is that we are here to write code because we are not you know in reality software engineering and you all are software Engineers is about decisions and trade-offs that's our job and that's what we are supposed to do you know code can be written by co-pilot my code is written by co-pilot plenty of times um but the code that I commit to our repository that decision was made by me and I need to understand what's going on I need to understand what's going on in the code and I need to understand the car of the tool only then can I make the decision if one line of code enters our repo or not it's about the tradeoffs of the tool and the decisions I make and you know who knows a lot about decisions and trade-offs typescript and the typescript team look at that it's an explicit non-goal of typescript to be proably sound which is a very bold statement for our type system but what they want to do is strike a balance between the correctness and the productivity it's a goal to make you productive as hell making all the little trade-offs that come with the type system that sits on top of JavaScript and that's okay the typescript team are some of the smartest people I had the pleasure to meet and it's tremendous what they do to formalize a programming language like JavaScript that's supposed to go hey why if you just look at it but that's software engineering and that's you know that's my point my point we are all developers and every line of code that you write is a decision that you make every tool or library that you use as tradeoffs that you need to be willing to take and there is no Silver Bullet so don't feel yourself Superior because you use a certain tool um a language everybody loves to hate his PHP but he here is Taylor ell the creator of a popular PHP framework showing off his Lambo that PHP bought um and then here you have lo and behold the Austrian Java F you know I mean hey if you all you need to do is carry kids and beers which car does the job um I'm a r developer by the way so have a guess what my car looks like and you know it's I mean that's a stup stupid status symbol but the key is there that everything that we use is just a tool and you need to be aware about the carard of the tool because I'm not here to tell you what to do I'm not here for the five minute hot takes that go viral on YouTube I'm here to make you aware that nothing is without its cards it's about tradeoffs it's about decisions and it's about productivity and with that I I want you to be pragmatic I want you to be aware of the trade-offs you make with the tools you choose and use this information to find and choose the best way possible for you and your team no solution is the best thing possible it's just a solution and one thing that was was interesting I think I think that's also the reason why typescript in the end is so immensely popular that they make this decision of allowing a couple of yeah type system flips for the sake of productivity there was another type system years ago called Flow by Facebook U which was syntactically very similar tooling wise very similar to typescript but also very strict and proably sound and I was at a conference a couple of months ago where I gave a similar talk to this like this to to an audience of 4,000 people and about everybody in the room knew typescript and worked with typescript fre people remember that flow even existed and I think this is because of the decision that the type system typescript team made in the past to allow the type system to be a little bit wider and not not proably sound for the sake of productivity so yeah it's just a solution and it can work for you maybe it doesn't don't go for hot takes or dogma and I know that this phrase on the slide is also very dogmatic but beat me and with that thank you again for having me again I'm sorry that I can't speak to you in person as you might heard right now I like to speak a lot and I like to talk a lot but something is preventing me from doing so um I still hope you had a great time um I still hope that I will be around in the chat uh uh to take your questions and to hang out with you a little um and with said I want to thank you very much for having me uh and if you want to know more about typescript I've written two books they are out both they out both are fantastic and I can highly recommend them but hey I wouldn't die right see you byebye