Conf42 JavaScript 2024 - Online

- premiere 5PM GMT

How typescript improves Developer Experience

Video size:

Abstract

Regardless of whether you’re working on a Greenfield project or a Legacy project, TypeScript is key to effectively managing complexities, especially compared to plain JavaScript. How much trust can we place in code with static type analysis? Can the TypeScript type system be considered “strong”?

Summary

Transcript

This transcript was autogenerated. To make changes, submit a PR.
Hi everyone. My name is Kasper Szefcik and today I would like to talk to you about TypeScript. And how TypeScript improves developer experience. But before I start, let me just talk a couple of words about myself. So I work as JS developer at RSC software. I work in Wroclaw, which is in Poland. I specialize in two technologies, Next. js and React Native. So as you probably already know, I'm front end slash mobile developer. And a curious fact about myself is that I am ex IT project manager. I was project manager for almost five years and for the past three years, I'm back as a developer. But that's all about myself. Let's move to TypeScript. And today I was, I would like to start with a story. A story that starts in 2008 and in the company called Microsoft. Maybe you've heard about them and in the year 2008 in Microsoft, there was an idea for a new project that initially was analyzed by business analysts, architects, maybe somebody else. And they decided about the technological stack and the requirements for this project. Later on, based on that, one of the team was selected to work on this project. And the project manager came to the team to announce them the news about their new project. And he said, dear team, I have a good news for you. There is enormous opportunity for you to work in the project in which you will utilize not only your beloved C sharp. But also another new technology, Javascript. And when they heard about that, it was silence. But after this short, brief moment of silence, They were mad because why they require them to work in this chaotic language, JavaScript, when on the other hand, they have their beloved mature language. S as it is C sharp, but the Microsoft, they were working as a professional developers. They don't regret or just throw away any challenges they face. So they decided, okay, we'll do this project, but we won't write a single line in JavaScript. So first of all, they sit and made their own analysis. Maybe they were wrong. Maybe the JavaScript is not needed in this project. But in the end, they found out, okay, it's in it. It's, it has to be running. In the browser, the JavaScript needs to be there. Okay. what they can do? They think, okay. We know C Sharp very well. What if We'll write the code in C Sharp With the whole logic that has to be done on this browser side But whatever write it in C Sharp we have all the tools all the libraries all the support that we have in the C Sharp and We'll just write the tool that to translate the C Sharp code into JavaScript And there was a tool you That's called script shop, which was doing exactly as they expected. So you take the file, the class in C sharp and just translates that into the function JS function It was a success for them They meet the goal They wrote a project in C sharp, which requires JavaScript, but they didn't have to write it. Success. But were there any problems? Of course. I would say that a lot of them. First of all, even though they have a beautifully written code in mature language like C sharp, Maybe even they have 100 percent code coverage, but they were testing the code that is not on production. That is the first issue. So even if they have 100 percent certainty that the code in C sharp works well, then it was translated by the tool that maybe not been so well tested. And then they have to manually test that when it was actually written in Javascript So the tests are false positive actually so they have Certainty of uncertainty, because they weren't sure that JavaScript itself is translated correctly. Maybe the tool itself contains error that generates errors on the translation. Maybe even some functions weren't implemented. And translate it correctly from C sharp to JavaScript. And they have to do it basically at each time of the release, each time of the translation that they have to manually test that. And if there are any problems, it was faster and more secure to fix that on the JS side, rather than fix that the translator, this script sharp tool. Why? Because if they change something in the scripture, maybe the problem that they had, they spotted, is fixed, but they weren't sure if something else wasn't broken in the meantime. So they sit again to the table, started wondering what they can do, we cannot work this way anymore. And, one brave team member asked them, What if you just write it in JavaScript? We'll do it anyway. Maybe it will be faster, better to write it pure in JavaScript. But the other team member said, nah, let's not do it. So this one team member asked, okay, but why? Why the JavaScript is so bad in comparison to ScriptShark? And they started wondering. Why? Why they don't want to write in JavaScript? Because everyone said that the C language is bad? Probably yes. But they just try to point out reasons why JavaScript is bad. And one of the things that they highlighted is that they are not sure what will be the result of the function that they are implementing. In the C Sharp they have to write in JavaScript. declarer, the types of the parameters, the output type of the function. So even if the function, if you provide the arguments of wrong types to the function, the compiler will say that it's wrong. If they expect different type of the method after execution, the compiler will say that it's wrong. So the application itself is basically verified even before they start to click on that or just execute anything. And they thought to themselves, what if Javascript will have that, then we can work with it. Because the What the keywords like the special words that they have in the JavaScript are not very different from what they already know. The only this predictability of the typescript of the JavaScript is. It's not existing actually. So later on in 2012, there was released the first version of TypeScript with the version number zero point 0.8. It was the first version that was publicly opened to the MPM. And what is very interesting about this fact that when you, when we compare the types of other languages that were released, that were developed as a new language, new big thing, then it was, you can see that most of the languages that were released, they took one problem or multiple problems that other technologies has. I didn't want to improve that, but this problems that technology technologies has, I usually connected with, or maybe different architecture and that's, we want to solve the issue with microservices to have better support in the language for microservice. Maybe, we want to improve memory management or, improve CPU usage of the language. in any cases, we want to improve some problem that one language has. We want to make it better. But the TypeScript itself doesn't do anything different. The applications written in JavaScript and TypeScript works the same. They have the same memory usage. Basically, they are the same application. What difference? It's a developer experience in writing in this specific language. The type itself was created to improve developer experience. It was created for the love, for the developers, or we can say for the hate of JavaScript. And it wasn't a huge success at the very beginning, at least. Because TypeScript in 2012 was supported only by one IDE, Visual Studio Code. But Visual Studio Code, even though it's right now, it's quite popular and many, probably most of you are using that on every day. But in 2012, it has one technical difficulty. It was running only on Windows. So it was a huge obstacle to overcome. But soon it was solved. Okay, let's leave Microsoft, and let's move to TypeScript. And because I started with the Microsoft, which for me, it's a company that earns a lot of money. And I will, I want To stay in the topic of money because who doesn't love money and for today examples how Typescript works with developer experience. I want to talk about the money that is provided by scientific grants. So if you don't know, grants itself is that the money that is provided by the government or some institution or the company to develop some research, scientific research. So usually it's like the long time project that you require, you write what you wanted to develop, what you want to discover in your research, you write some expected results, and then you proceed with the research. So usually you need to provide the document that describes what your product will be about. what do you need to buy in case of the consumables, any materials, any devices, that will help you to, to basically make this research and then write any results that will help you. you expect to, to be, receiving or any applications for this research, if it will be a success. So this kind of grants grant, contains, let's say a couple of informations. and if we want to have a system that allows to upload this kind of data, we need to store it. so the, first of all, we need the information or the applicant, as you can see on the right, we have some name, of the student or the supervisor. we have some magic number, which is basically the identifier, for this specific person. so we know that he or she, apply and this is not somebody else from different university, for example. We have some new address, maybe some different information that is specific for this person. And the other thing is application number. so this is something that we'll just point out the exactly which of the, application it is, especially the application number on the contains information about the Institute, maybe the funding for which we are asking for, probably it will contain some year, when this project is Submitted and so on. so we also want, it won't be just, the index from the database. It has to be something first of all, a little bit secret, but on the other hand, quite descriptive. we'll have some information of the project. Of course, we'll have attachments, which are quite important. Because it should contain any offers that we already ask, for the companies in case of this, devices that we want to buy or rent, maybe this, materials that will require for this, research. We need to have this kind of offers assigned to the project so they know that if we are asking, for example, for 100 grants, this is basically the summary of all the costs that are in the attachment. and the last part that I wanted to highlight is the signature of approvals. because, this kind of project usually have multiple steps of approval. in the Europe, And there are this kind of projects, they are all, always at least two steps. The first one is something that is called formal review, which basically verifies if the application itself is correct. all the fields are, filled correctly, basically. And if the information that you put are according to the truth, if you are applying for the correct project. And so on. So on. And later on, there is, the final review, which will basically review if your project are, interesting or needed in case of the actual situation of the market. so let's say that you are applying for the grant, when three years ago, there was very similar research, done, and you are basically asking for the money for very similar, even the same research, you won't receive this kind of money. but usually it's on the second step because it requires somebody from the industry to verify if your product is correct. yeah, so let's start from our first part, ApplicantData. We have this kind of basic type that we will have to, map our applicant data. So you have some kind of address which will be used for correspondence or any other, sending of the letters and so on. As we have some city, postal code, country, Let's keep it simple for right now. On the other hand, we have this applicant, which will be our basic, unit of the user. So we have the first name, last name, email, phone number, address, and SSN, which is stands for social security number, which is the. Unique identifier for the people with, the U. S. citizenship. In Poland it's called PESEL, and probably in other countries it's a similar, number that is unique for this specific country and this specific person. But If for example, I would apply for the grant in the United States, I don't have SORA security number I can probably ask to receive this kind of number but If I don't have the citizenship, probably I don't have it, let's say, right now. So usually in this kind of, in this kind of applications, we're asked for a different data that will also allow us to identify this specific applicant. So if we don't have social security number, maybe let's fill up birth date. So in this case, if we don't have social security number, we provide the birth date. If we have social security number, we don't need to provide the birth date. So in this case, let's just put that both these values are optional. But this is not the only one who can ask for a grant because also the companies can ask for a scientific grants. So in this case, we won't provide social security number because we are asking as a company, not for the specific person. We won't have the birthdate because the birthdate of the company It's not interesting for us. But what we can ask for is a company name and their tax ID. So again, tax ID is something unique for the company in specific country. So if you have that, maybe you have the company name just to fill the form. Then we have the whole object of the applicant. So right now we have four optional fields, but we require that at least one field based on the, based on the type of the application. we need to, we need that it's filled. So let's improve that. so we can start with that. So we have the private applicant, which contains all the field with social security number. Yeah, that's our basic type. We can, have the separate, separate type for private applicant without social security number, which we don't have social security number, but it will have birth date. Okay. And the last one, we have the company applicant. which will contains, contain the first name, last name, email, phone number, address, and the company name and the tax ID. And if you want to group that, so we have applicant will be one of the three, three types and basically that will work, but we are repeating a lot of fields in the types. Let's improve that. We don't want to repeat ourselves dry principle, right? So yeah, let's improve that. So we'll create the base applicant type, which will contains five fields that we have in all of the fields. So we have the base, the private applicant, which will contains base applicant and the social security number. Private applicant without social security number will contain the same and the birthdate. And the last one, company applicant will contain base applicant and the company name and the tax ID. yeah, that's basically what we can achieve. And we can achieve that in any other language. the problem is the solution. Is that I don't like it. the biggest problem that I see in this, in this approach is that we are not secure from the creating of this, base applicant type object, because the base applicant itself is something that is completely not connected with the business. So it creates some dummy type. Because we as a developer, we don't want to repeat ourselves because we have a dry principle. But on the other hand, we are creating something that's doesn't represent anything in case of the business. Like we cannot use base applicant anywhere. We'll still need, with social security number, with birthday, or with company name and the tax ID. And apart from that, that this type base applicant is not exported outside the file. This is our, the only security right now that we won't create an object of this type. When you compare that to, for example, C sharp or Java, In this languages, we can create interface or abstract class that we won't still be able to create the object of this type. We can create an object which implements or extends this kind of interface or abstract class. So in this case, we said, okay, I know that this object itself is more complex, but I want to work only on this couple of fields with this limited number of fields, limited number of methods. And this is what, interfaces and abstract classes are for. The typeface itself doesn't allow us to do So we are creating dummy type, which are basically just for our convenience. But the problem right now that we have some, let's say, base part that first of all may vary and will affect private applicant without social security number and the company applicant without our knowledge. Okay. So let's use something that DevScript has already in the language. which will help us solve this issue with creating a dummy type. And not repeating ourselves, of course. So let's start once again for a private applicant with social security number. Let's take it as it is. This is our basic type. Most of our applications will be created by private people with social security number, so we can say that this is our basic type. If you want to create a private applicant without social security number, we can, for example, use the omit type. Which basically takes the type that we provide as a first argument of this generic type. And we provide the list of the fields that we say, okay, skip this field. And when we have the type that is declarative like private or pecan without social security number. So we just say, okay. Omit social security number. It's exactly what we are, we are, we say that we will have. And we just add that to the private birthdate. So yeah, in the background, we are actually creating this dummy type, which won't have this social security number. But in this case, It's not access, has access anywhere. We have to declare that this base applicant omit private applic, applicants, social security number to be able to export that, outside of our function. This way it's not access, accessible. In case of the private applicant, I would recommend us to use PIP. First of all, because we are taking specific fields from the private applicant. If the private applicant will receive more fields, I won't expect that the company applicant will extend on their own. I want to have in this case, the full control over what fields I'm actually putting into company applicant to have the same type. The same if it's optional or not. And so in this case, we just take this all five fields and let's put them. So in this case, we create again, the dummy type with different way around, but we have a full control over which fields are actually included in that. What also, provides us, let's suppose that the private applicant type will change slightly that we get rid of first and then the last name and change that into the full name. So in this case, it will affect the private applicant without social security number, which also will change its type. So it won't have full name, first name and the last name, and will also only have full name. But in case of the company applicant, it will tell us an error. Because the compiler will say, okay, there is no first name and last name. we have only full name. And of course, this is required, this requires us our manual log that we have to update our type. But if there is situation that we still want to have for the company applicant, the first name and the last name separately, okay, we'll have to do it manually, but we'll do it either way. And we have full control, full knowledge that something is crushing our application. That is the advantage of this approach. Okay. Let's leave applicant data. Let's move to application number. So in our case, let's assume that the application number is something like that. So we have some code, some numbers, slash, and the year. So first of all, what we can achieve with the TypeScript? We can say, okay. That's. The application's number will be just a string. So we can declare in the type of our whole application that it will be a string. Or, we say that okay, we'll improve that in the future. So maybe instead of declaring that as a string, let's say that we have the type application number, which right now it is a string. Maybe at first it doesn't change anything, but later on if you change this type, it will also affect all the types that you want. And we don't need to search, okay, where we use string as application number, because it should already affect the whole, the whole of our file. So first of all, we can use something that we can say that. There will be like application type codes that we declare as a list of the codes And we can declare the years That will be like this five years. So the years when this Grant scientific grant is actually given for the specific project So if we have something like that declared We can create a type, which is TemplarLiteralType, which will contains of application type, number, and the application year. how it looks like. So if we create this, something like this literal, Templar, TemplarLiteralType, it will generate us all the possible combinations of our codes, number and slash year. So in this case, if I, for example, change that to 2025, it will highlight that this value that I'm providing is not correct. in case of the temporary data types. Again, if I don't put a number, it will also return an error that this field is not correct. So using just this very simple native mechanism of TypeScript, I can create already type validator based on that. I can already set, okay, this is correct, or this is not correct. I can verify if this first code after, somebody puts that manually is correct with this type of code, because I know that this type, this application number will consist of all these fields. Zinac normally would need to have some kind of complex regex, just verify that. TypeScript has regex included in their language, and that's beautiful. Let's even improve our, our application number type validation. And just play that, play with it a little bit so we can add some kind of generic type. That's, I will just describe that in a second. So we have, again, application type codes. We have year endings, which generates, the ending. I have application year. so we just put something we don't want to repeat ourselves. Again, and yeah, we're going to generate the same code once again. and how it works basically. So as you can see, we just provide, a number, which is this first argument of our generic type. We provide that we want to receive the, array of numbers and what they are doing basically. if results of, length of this array with results, actually extends our. argument. So basically that means that if the results equals our arguments, return results. If not, just add additional result to our, to our array. So in this case, it just generates numbers from zero to, to the size of the array. And yeah, that's how it works. And as you can see, it's quite dummy because it can, it generates us this kind of error. So in this case, it's better to use it, until then not higher. Okay. Let's move to the attachments. with the attachments, let's declare that we'll have three types of attachments. So again, we'll just use union on the expenses, income, and the other. Whatever it is. And with the attachments, usually we have two problems in the application. That the type of the uploading the, attachments it's completely different from the. Type that we receive apartment, because usually when we upload that, we using some, multipart request, just upload the fields and upload the files. And in case we want to get that, we receive your, with the file. so we can download that. Or if it image, if it is a image, we just, Render that as an image. So in our case, we can have attachment details, payload, which will contains the file that we'll be able to upload, using the multiple request. we'll have the description, what type of attachment it is. we'll have the type. So just this general. Category of the attachment and maybe we'll have also the page count which will be basically the number how many pages of this Attachment there is actually is So based on that, we can verify if all the documents are, correctly uploaded and when we wanted to get, the details of the attachment. So again, we can use the PIC that you already know, attachment details payload. We take description type and page count, and we just add firewall, fire URL. yeah, based on that, you can handle both upload and post and get requests and post and get request data. Maybe even add some ID in case of the getting the, this attachment. But what we can also do. You can add attachment name, because usually we'll have, maybe we'll have some name that attachment that's also always required, like CV or some motivation letter. but any other generic general, attachments will have probably this attachment plus number. So we also have, we want to have this kind of, assigned for our keys. And the last part, because we don't want to create an array of the attachment, but we can create an object of the attachment. And in our case we can create an object of the attachment name, which will be the key of the attachment. And attachment details will just assign the object. in our case, we'll have something like that. So we'll have, okay, so we'll have just the object of this specific key. and the attachment details, which just generates us with the, the attachment. And based on that, we can, for example, access the attachment number two, without iterating over array or going to the specific. index of the array, we just ask for the specific, attachment and we can say, okay, it's present or not. And so on. so yeah, if we group that, that part, so we have the application, which consists of the applicant with the applicant data, we have application date, we have application number, which we created, and we have attachments and here I will use the partial, because once again, we are not required to upload always the same number of, attachments. So we would like to have this kind of, optional for the keys. So we just upload only in this attachments that we actually needed. And yeah, if we have the application that has three actually types of the applicants. just to remind ourselves, the applicant, applicant without social security number and the company applicant, then, and of course, in other cases, we'll need some type guards, and how the types that works. So we can have this kind of function is object with key, which basically verifies us if the object. Is key, if the, the, the argument that we are providing is actually an object. We also verify if that is, not nullable. And yeah, just basically to, to be sure about that. So argument that you have provided is the unknown because we don't know what it is. And we return that, okay, this is an object that has some keys and, we don't know what is the type of the. of this keys. So we just return, okay, it's unknown. so yeah, that is our return type. So in our case, we just verify if the applicant that we are providing is actually a private applicant. So in our case, We can say, okay, is a private applicant. So we verify that if we provide an applicant, which is unknown, we can provide an applicant that is application that will also work. we say, okay, applicant is a private applicant. So in our case, we just verify if the applicant has. This object with the keys and does it has, this property social security number because it was unique for our private applicant. Of course, we can verify multiple fields, in this type guard. In our case, social security number is unique. And I decided that, okay, the type that is solved will be sufficient. If we verify the social security number, what it gives us, let's look at a look at the example. so I make it a little bit simpler just to fit them on one screen. so we have a type private application, which will contains only the social security number. So we don't need any other fields. Okay. And our applicant will be private applicant or string. so yeah, we want to verify that first of all, it's an object and not a string. And the first and the second thing that we wanted to verify if this is actually social security number. so yeah, we have the same function. And what it gives us? If you have the method that say printApplicant, it's not very complex, and we have an argument of this function, and that is string or privateApplicant. And we have the if clause, which right now they know that, okay, it is an applicant. And, but when we enter on this method, so inside of this, scope, the type, you already know that this is private applicant. It will say that, okay, yeah, that's right. It's a private applicant. If we, add additional. line here, and we will say, okay, applicant, let me just verify that. Yeah, because it's outside our if clause, it's actually in the else clause. It knows right now. Okay. It is a string, not a private applicant. if we just go, beyond that, okay, I will just remove that. So again, outside of the, if. TypeScript doesn't know what it is, if it's a private topic on this, of the string. So again, if we just try to use that, especially in this complex types, and then the types we already will say that, okay, we are not sure what type of method it is, even though somewhere in the back, before we execute this function, we know, okay, this is something else. the types of itself needs to be certain and we'll just return those error. We can fix that before checking that on the code. Okay. so let's look in another helpful, additional national type. in case of the hour. Application will have the fields that are not changeable at all. And we want to maintain that. And to do so we have the read only. so in, let's say our basic type, so we have read only and again, we have the application number if you wanted to. to change the value, to override that, TypeScript will tell us we can't do that. So in our case, We'll have the situation that we have the whole application completed and somebody will verify it's correct and later on just assign, okay, it's correct, give them money or not. So we would want our whole application to be read only. And only the verification date, verification status. And who verified that? Which are the only fields that you want to be read? to be, not read only, and all of the others. We wanted to stay at the same. We want, we don't want anyone to edit our fields, so in our case, in our application, we can force that the argument that we provided, the methods will be written only. And only specific fields will be actually editable inside of this method. So again, we can make sure that nobody change, change the fields that you don't want them to change. The last thing that I wanted to show you, is creating a draft because the grant submissions are usually quite long, to write that it requires a lot of time. And even if you start uploading that into the system, maybe you receive the information that something is missing and you have to abandon the process, to gather the documents, maybe from your university, maybe it's from somewhere else. and yeah, you will need to go back to that after a couple of days. So in this case, The draft functionality will be very important in our case of the application. So how we can do that with the TypeScript? so we can create something like that. So we'll have the applicant, which will have first name, last name, email, address, and social security number. We have the follower application, which contains applicant, application date, and some application number. Let's keep it simple. and we can create our own type, generic type that is called Nullable, which contains null or our, argument. Later on, we can create a DeepNullable, which for each. key in our type, deep nullable of deep nullable of our, key. In this case, all of the fields in our tree will be nullable. So we can create an object that will, for example, will be have, will have, nullable application date, nullable application number. Nullable first name, last name, email, social security number, but in the address we'll have only field, for example, city. With these four lines, actually we create very powerful type that will allow us to make a magic. Of course, there are still challenges how you're going to save that into the browser or even into the server. If you have all the fields nullable. but yeah, from the directory point of view, four lines and you have very powerful field. You can even change that from null to undefined, and then we don't have to provide all the nulls, just one field. Somewhere in the, in the background that will be filled. so I have two key takeaways for you. use advanced types to create complex types. Because, there are tools that you should use, and they are very powerful. And typeguards allows for safe and fast typechecks. Again, If you're, for example, verifying even the API calls on your local development, if after verifying the type that you receive from API, you receive an error locally, you're still benefiting because very fast, you received the information, okay, something changed, some field is missing, some field changed type. And you will be able to update that very fast. yeah. Sources. so first of all is the whole, story from ScriptSharp to JavaScript. and the other thing is TypeScript documentation of TypeScript 5 Minutes, which contains all the advanced types. some of them I just highlighted. I think that there are the most popular, at least in my code. but yeah, maybe there is something else that's, that is there. And that you feel stuff in that's, maybe it's useful, it's better to use something that's already there in the language rather than write it yourself. Yeah. Thank you. That's all from me. Do you have any questions?
...

Kacper Szewczyk

React Native Developer @ RST Software Master

Kacper Szewczyk's LinkedIn account



Join the community!

Learn for free, join the best tech learning community for a price of a pumpkin latte.

Annual
Monthly
Newsletter
$ 0 /mo

Event notifications, weekly newsletter

Delayed access to all content

Immediate access to Keynotes & Panels

Community
$ 8.34 /mo

Immediate access to all content

Courses, quizes & certificates

Community chats

Join the community (7 day free trial)