Conf42 JavaScript 2021 - Online

TypeScript's Strict Compiler Options

Video size:

Abstract

Technologies: Angular, React, Svelte, Vue.js (comparison of TypeScript –strict in those), TypeScript, and CLI’s mentioned frameworks.

Problem: Many of us don’t really understand what’s the strict mode all about and why there are several different options. In addition, TypeScript strict rules are off by default; only Angular CLI asks us if we’d like to enable those during a project generation. Sometimes we’re even scared to enable those in less .ts- friendly environments.

Solution: We can enable them manually (only Angular CLI helps to do so automatically), but to understand why those are sometimes frustrating, a little explanation during the talk might be helpful based on pure TypeScript real examples

Audience takeaway: strict options are here to help us write better code, but without stricter linter options and/or understanding it, many issues have still doors open

Summary

  • Daniel will walk you through types those compile options. The strict rules are mostly around in those highlighted red zone. If you'd like to discuss a little bit more, you can just scan the QR code Andor connect with me via LinkedIn.
  • TS config is of course in the compile options. You can set up extra checks to make your typescript to be more strict. The first rule we'll touch upon is not implicit Annie. Follow up with other examples to hotspot which part of the code was problematic and how we fix it.
  • No unused locals it's about not unused local variables. Stricter note checks so that's one of the reasons why I skipped this very simple flags simple options. There are some compile options which are more essential I would say, for this presentation.
  • There no fall through cases in switch. Propertymessage does not exist on type unknown, which means error. To fix this we need to put this in an if statement. We also need to enable strict nutrition before. Most of the code bases are without this.
  • Ustrick makes sure that your javascript is in a strict mode, not in a sloppy mode. Strict enables wide range of type checkings. There are many other rules which are not enabled. It's recommended no implicit use stricter.
  • The compile option is about improving code quality. Allows synthetic default imports. Force consistent casing in file names. Allows you to create react apps. At the end of the presentation I will go through single page application frameworks and how they integrate with strict.

Transcript

This transcript was autogenerated. To make changes, submit a PR.
You hi, my name is Daniel for the Conf 42 I'll walk you through types those compile options. If you'd like to discuss a little bit more, you can just scan the QR code Andor connect with me via LinkedIn. I will be happy to answer more questions. So types compiler rules, type risk compiler options what it is about if we would like visit the technical documentation, we'd see a bunch of rules and it's really like difficult to walk through all of them. It requires lots of time and attention. Our presentation is mostly about this part which is highlighted in red. We'll also touch upon a little bit of the compiler option from different categories, but the strict rules are mostly around in those highlighted red zone. Before like few minutes back the way how it was divided Andor in the documentation was a little bit different, so we could explicitly see which are strict checks which are for example interchecks. Now they kind of compiler this and then they call it type checking, but those rules are still the same, they just categorize it a little bit different. So we are starting on the TS config. I hope most of you know what TS config is. This part of the TS config which we will be talking about is of course in the compile options, and within the compiler options you can set up some extra checks to make your typescript to be more strict or for certain rules we will be talking about the first rule we'll touch upon. We'll start slowly. It's not implicit Annie, and we have a very first code snippet sample function which has a parameter and our implicit n is disabled, or it's false, or it's not set up at all, which by default it's false. And by the way, this is how the presentation will start with each rule. On the top left corner you will see the compiler option and in the middle you will see the code we are talking about. But with no implicit any actually types would pop up as error that this parameter implicitly has can any type. By the way, maybe some of you have noticed, but this no implicit any flag has changed to true. So to helps you guys to map when what is being shown. For example with the true it will be always see on the screen that there is some kind of error or a warning at least. So here we can quickly see the implicit sample dont implicit whats can n type and we can quickly fix this by adding string to hotspot. Where was the problem? It was in the parameter and we have added string. Those is also how we follow up with other examples to hotspot which part of the code was problematic and how we fix this next one. Also related, no implicit this time this code as the first glance looks fine and maybe even before preparing those presentation I would also say, yeah, it's completely fine, but there is something which every now and then I have seen as my ide. But let's first enable the no implicit disk and now we can see what those id is complaining about, namely this implicitly Andor type. Yeah, and this actually is a little bit confusing because typing this might be a bit counterintuitive for many of us. And for me, for example, it also was I have to express, but there are actually two ways to fix this in a way that typescript will be satisfied as well with the no implicit enabled, the first option is to make an arrow function, and that's actually it, you don't have to do anything more. The problem was here, this was the hotspot I would say of the error, and we could fix it like that. Okay, simple. But there is another solution, maybe more intuitive some, I would say for me it is because I can quickly see that this is explicitly set to those total amount, which in this example is the class. And in that way we fix this error with setting this in the parentheses to total amount. No implicit returns. For returns follow the similar logic as no implicit n and those. So I have quite some rules to go through, so I will just skip this. But as you follow the first two examples, I'm pretty sure you can conclude what it is about no increase override. It's actually interesting one up. I wasn't. Yes, it opens up and up. It didn't go no, it here we are here maybe in typescript, actually we don't, it's not that intuitive or javascript was of course slightly different Java, but for Java guys they could quickly see whats they would realize what it is about. For Javascript, including myself, it might be something new sometimes. So this flag tells us that if we have a class and we override whats class like here, so we have another class which extend the class andor we override this, then basically with this no implicit override, we kind of cannot do this if there is the keyword override. So if we have overwrite set up and the flag is enabled and we try to override sorry, we basically, when we extend the class and we override, we have to explicitly say that we are overriding. So it's not like implicitly set, it has to be the keyword. We are getting back to the presentation now. Unused locals it's about not unused local variables. Once again I will move forward. The name says everything. I would say the same about no unused parameters and allow unreachable code. That's something which I would just copy paste what's from documentation here with this, like you don't have to do anything. By default it's undefined, which means you will get a warning in your ide that yeah, those is a code which is unreachable. It's a small synthetic improvement, but still we don't want words like that code aloe unused labels and once again I will take a little bit from the documentation. It's actually same as aloe. Any tribal code id will give you a documentation, but it's very rare that you will see it because in javascript we don't tend to use libraries that much. Maybe when you'll be working for object literals you might spot this. But even if you'll forget about this Andor most of probably you will about this compile option, then by default you will get a warning. It will still compile to Javascript, but you just get a warning. Stricter note checks so that's one of the reasons why I skipped this very simple flags simple options because there are some compile options which are more essential I would say, for this presentation. Andor first of them is stricter null checks. This code also like without this enabled, your id actually wouldn't help you, I would say wouldn't tip you. But more experienced or even middle experienced developers could quickly know that okay, those greeting whats a string? And now it's a null. So there is something phishing definitely. And it is because if you enable this we can quickly see that type null is not as enabled type string. So that's the first, let's say parasite stricter compiler option from typescript we spot on this part of the code which we fix this by adding an extra type. Yeah, of course writing to null might be like a bad practice in general or in most of the scenarios I would say. But from the compiler options, if you are writing to Nordis, how you can fix this? So we had the problem here and we have based data strict property initialization, very basic example. Many would say yeah, everything is fine. I think quite some would say yeah, we are missing initialization and if we will enable this rule, then something will pop up here. Little note, if you want to have to enable the strict properties initialization, you have to also enable strict null tracks. Basically if you put the strict prepared initialization to true, then you have pop up from id that to have this working you need to enable strict null checks. So they are working only both together. I mean stricter project initialization requires strict null checks. That's better to say. So with those two enabled we can see that property name has no initializer. Andor the fix is basically very trivial. We just need to initialize this. Those hotspot was here. We fix this by initializing string string functions type function types. So it's slowly become interesting I hope. Yes, this will be example go to our ide at. At first glance it looks completely fine, but maybe some of you would already notice that maybe string or number. String or number. String or number. And here we are passing number and we are putting this to lowercase. So watch out whats will be happening. Okay, let's enable strict function types to true. And we have actually pop up from our ide. It's complaining about the type okay, which means that there is something wrong. We will hotspot the place which we have to make the fix. Let's say fix. So we just. But the number here, okay, I'm sorry, let me get back. We put those number here Andor something different pops up now, okay, which means that if we follow those, as I said at the beginning, there is some fishy. We pass number and two lowercase, okay, and now we can see that the type C three compiler options helps us to avoid bugs actually, because here if we pass those number, even though here we are fine. Then thanks to the case that we have strict function types to true types shows us okay, here actually it doesn't look good because it's one of those, okay, if we put a number and to lowercase to lowercase works only on strings, okay. And with strict function types to false, it didn't say about this part anything about sample parameter and it didn't even say about two lowercase, which is actually the essential problem in this snippet cost snippet. So I'm highlighting, we have added the number Andor types help us to actually spot where is the real problem. And here I will have a very simple example. Let me put examples. Okay. I just open this for you guys. It's a quite small example, okay Andor let's disable this to false, okay, here everything will be fine and we will also wait, let me make it that way. So I will remove it here and we see that whats the error from the presentation and we make it false now. Okay. And takes time but yes it works. And what's happening now we'll compile the typescript file to Javascript it did. What will happen now? Let's say we deployed those part of the code somewhere and user has clicked there was some kind of place to put input and we try to but to input to change the number to lowercase and what will happen? Yes, our users might have a bit unpleasant experience because it may throw error and yeah, most of a bit is not what we are looking for here. It was a very nice example how typescript can hotspot thanks to the typing can hotspot actually bugs here. The embedded two lowercase typescript method actually expects a string because we will get back sorry, not here. So now we have the proper types, then we can see that okay, to lowercase doesn't exist. So before deploying most of probably to handle it somehow. Okay, let me get back to the presentation. Yes, this is what I said that were was a problem not spotted. And now here we have all the hotspots. So first type complain about this one. We had to change here. The parameter was problematic, but at the end of the day the lowercase, those lowercase, it was the problem where it whats actually the but strict bind call and apply this option. I will skip. It's a nice one, but we dont tend to use bind call and apply that often after the ecmascape six came. So if you want to check it out, just take a look into the documentation. It's explained quite well. There no fall through cases in switch. That's interesting. One we have switch and cases. Our fall through case in switch is disabled, but we enable this and what happens, we have a warning. Okay, and to fix this we just basically need to add break because type six spot us that. Okay, this case ends without break. And here I also have one little example because I think this one is much a bit easier to follow if you see those real example hub. Okay, so I will make it false. Okay and I will remove the break andor now I will compiler TSC, six ts and now we can see even at odd, even though the number is zero. So it should finish here. But there's four through so it goes actually to one. The log actually I could put here maybe two. So it would be even and odd as more logic. But I hope you guys realize that it's just naming the essential parties. This one and this one. And now if we will compile this one more time, or transcompile to be more precise, then we can have see only event which makes sense. We gave zero to double check. We are in Javascript. Yes we have break perfect. Okay, so here was the problem and we fixed it by adding break exact optional property types, so becomes interesting. It's not like stricter per se, but there are also quite some types I will cover which are a bit like a bonus. So this one, it's getting slowly advanced because if we have the h with question mark so which is like optional andor we put it to number, then actually it's equivalent to number or undefined. So those using this interface here with these properties actually without exact option. Now property types seems to be fine, but actually it's not. And here one more time for those compiler option, we also need to enable strict nutrition before. Once again if you will enable exec optional property types first, the IDE will guide you that you need to first enable strict note checks. Okay, so we have this enabled and we can see that there is little problem. Type undefined is not assignable to type number, which means that fix should be quite simple and it indeed is. We have the number and we can just add undefined. So those function like you have something optional but you really don't want to use it, you want to put undefined, that's fine. So this is actually more readable as use unknown in catch variables. Getting long right. This is can interesting one. It's a very common scenario we use try and catch of course, and if you enable this flag then what will happen? Something weird actually propertymessage does not exist on type unknown, which means error. Error is unknown. I think it actually makes sense because we don't know what kind of error will come up. For now it's unknown. Or let's say for now it's unknown. Sorry. To fix this we need to put this in an if statement and actually if the error is instance of error then it will be gone saying in a very simple words here we can see were was the missing part and we have had whats if error instead of error then I believe that most of the code bases are without this. While preparing the presentation I read that it might introduce some, those might be some problems without using the if with the if, it's definitely more readable, but how serious it is if we won't put the if error is. Actually, to be honest, I don't. I am not really sure if there's a major risk for your code, but once again if you would like to maybe discuss a little bit more, you can reach out to me now. Always stricter. Yes, for that we have documentation. I think now this part of protection will be quite a lot with documentation always stricter is basically about the use stricter, so it means you actually should have it enabled, because ustrick makes sure that your javascript is in a strict mode, not in a sloppy mode. Sloppy mode is the code which sweep out script and it follows bunch of rules making the javascript less error prone, et cetera. Strict enables wide range of type checkings, some of them we covered, right, for example stricter bind colon PI said yeah, I mean we don't use that often bind colon apply let's say anymore. So we skip those, but all the others we actually talk about. So you might think okay, you put strict to true and all the typescript compiler option will be enabled for you, so you won't introduce any bug. But actually if you would get back to one of the very first slides, you'd notice that okay, we had a bunch of doors, bunch of rules, and some of them are in type checking. Some of them actually are somewhat different andor some of them we still didn't talk about. So yeah, I don't expect everyone will go through the whole documentation to enable all types three compiler. But just to be aware, if you put strict to true, that's already progressed. But be aware that there are many other rules we talked about and we have still a little bit to talk about which are not enabled. So with stricter true your code won't be like ideal or absolutely zero error prone. So diving deeper imports not used as values I said I have documentation here for some of those triggers. Actually it's not always it to find example, to be honest. So for those part documentation covered quite nicely by default. If you have values of types important never use during complete translation, it will drop this. If you want to preserve this you can enable preserve, but I don't recommend this because it can introduce some side effects alternative. If you really want to preserve them, then you can set as error and then the typescript compiler will show you that yeah, you have imported some type or value, but it has been never used here it's more like information with the default remove you are fine. Skip lip check Andor Skip default lip check skip lip check points you to skip to default lip check Sorry Skip default leap check points you to skip leap check sometimes it might be case that the libraries which you're using define two different types and skip leap check will make sure that the type c will not check both of them. So actually that's a trade off between performance and strict so if you want keep kind of like a bit stricter rules. It's not strict per se, but it's kind of strict. So if you want to make sure that it will check dependency a and b, if the types are correct, then you just keep it. If you are looking for performance improvement then you can just put true. But basically whenever you are facing this issue, you mostly read about your resolution or overwrite. But this is also something which typescript has force consistent casing in file names. I think it's self explanatory. For example, your file will be file manager in upper camel case. I think for this for example will be very familiar for many people coming from react background because the ecosystem and documentation kind of guides you. But here if you can make it, you would like to make it more strict and have the check automatic, then you can also think about this. As you can see it's recommended no implicit use stricter. Actually you will never use this I believe, but this rule and the next one is just to be aware that there is something like that. If you would like to. If for some reason you don't want to have use strict when emitting a module to a non es six target that's actually important, then you can put it to true. But 99 dont andor eleven 9% of you guys dont need it and I'm not going to use that. But it reads kind of too strict rules. I want to cover as much actually everything in presentation, so I did include those, but you're not going to need it. No. Typescript generic checks. Once again, this is good by default. This is set correctly by default. It protects you by default. I cannot imagine that someone would like to set it true, but for you to be aware that for these kinds of scenarios, typescript also protects you by default. That's nice. Another flag. Here we are in flags which actually are set nicely corrective for us by the TS config. Once again, typescript protects you from this kind of scenario when you have a type and you are trying to create a variable with this type, but with property inside which is not defined. This type, please keep it. Another one suppress implicit andor index errors. Here we are also protected by default because for example, imagine that we have can object and we are trying to access foo, which actually doesn't exist. Actually you can put this to true or put a TS ignore on this, but that's a really bad thing, so please don't do it. Once again, we can see that yet another scenario, typescript protects us by default disable fine line based system type acquisition. That's a very small thing actually, but it's relatively new. We have in typescript for one, since typescript for one. For example, if you have a jquery JS, then it will automatically download the types for jquery from definitely typed. So here I cannot come up with a scenario when actually I could think to use it because mostly I just install everyone just install the package and it automatically gets everything. But if for some reason you have js file and you don't want those types to be downloaded automatically, you can set this to true. What can I say more here? Very niche, that's a good word. Now we are outside typescript world, but typescript compiler options also has some rules related to JavaScript. For example, allow JS by default it's false. If you want to allow JS modules to be imported in your typescript project, you can set this to true. Another is check js. So for example if you allow js then actually it would make sense whats you also but checkjs to true because the check js will check if those imported JavaScript modules are fine. So actually you enable this only if allow JS is enabled. Same for max node modules js depth by default those is actually option about how deep you can go through node modules to import the JS module. And you would of course enable this only when allowed. JS is true because otherwise if you cannot allow js then what's those point to put this one, if you cannot import js files, the previous one allow js and checkgrid you might use sometimes, but this one I don't think so you will use it to offset, to be honest. Now we have a couple of even more advanced compiler one moment, sorry, no property, no property. I'm not sure why the hyperlinks are working really bad. Sorry for that. So what's happening here? We have interface and we are assuming that whatever is like here, it's unknown. Whatever comes extra to the interface then this is a string, okay, so we say yeah, for example string speed quality, it's there, it's there, so no problem. But what's happening when there is string username which is not here? And this is what the compile option is about. If you turn on the flag then okay, this is continuation of the previous code, okay, you can see speed quality, speed quality okay, and the interface is also here, don't worry. So we can see that those property username comes from an index signature, so it must be accessed with fusion. So if it comes from index signature. So if it's annoying the interface and you want to put something extra like property were, then for the case you can distinguish in the code that you are doing. So you have to access it differently, namely like this. In that scenario, while reviewing your code, you can actually see that because of course when equivalent object in JavaScript we can access the property via dot or via array, okay, and put some value because we can see that let's say those interface defines somewhat different file whatever and we are going like this, okay, then we see, okay, those two are defined, but when we see something like that, then we can distinguish that those is unknown for the interface. So we can actually conclude this very quickly. It's more like code quality improvement, I would say a bit advanced, very kind, sometimes niche, but this one actually might be used sometimes. Now no unchecked indexed access I will access it here because it's nearby. Again we have interface name OS inside. Again unknown properties are covered by this index signature. And what's happening here, this is not declared Andor it's still as a string, which kind of makes sense because this is how we time. But let's think about the unknown keyword with this flex enabled. Actually we would notice that this one is stringed or undefined because it was unknown, so it might be also undefined. Andor this compile option will help to spot this information. Allow synthetic default imports I will look like this synthetic default imports. So here is when you are importing a module and when the module doesn't have a default, which you can import. So if the module doesn't have those port, this flag will find this, but disable size limit. There are some memory related memory things in typescript. It's not related to your code, but it's actually related to testing behind the scenes or under the hood. And if you put this to true, which I wouldn't recommend, then you might run in memory related issues because otherwise, which is by default there is some kind of size limit which typescript allocates for the memory. So it's a really low level thing. Guys, if you want to read more about there are the official documentation, there are two links basically you can also check this one and at the end of the presentation I will just to go very quickly through single page application frameworks and how they integrate with strict we have react which by default has some rules enabled. Okay, and look guys, you remember how many of rules we went through it. Whats strict? So without taking this printation we think okay, everything is fine. And we even have no fault through cases in switch before it was so called a linter check. We also have some force consistent casing in file names. I said this might be familiar for people from react because this is actually enforced by default. If you are working with types of CSX in react, then yes, then it kind of enforce you. I think if you generate react code with Javascript, then it's also enabled the force consistent casing in file name. So that's a good thing for react. And we have also a couple of others, few others. Okay, you can generate probably create react app. But some of the frameworks, if you add flagstrikes, then they will generate a different ts config. I will show you very quickly here in react, the strict doesn't work. So we have those rules by default view js two strict skip blitz check and allow centering default imports. When I checked on view JS three, it's basically the same if you generate the view JS with typescript. There is just one extra not related to our presentation compile option angular. Angular came with typescript, so we would expect quite a lot actually here and that actually working in angular you can generate your project with Nginu and you can use the flag strict, which would add some strict rules. Without this it won't add anything. And here we have strict no implicit returns and no photo casing switch. Those two actually are the all, let's say linters force consistent casing in file names. It's also being added, and in those default one it's not. So here actually react did better job, to be honest. Sorry. In addition to that angular access also it's all compiled options. And when you run this with strict, it also will add something on top of this. So this is actually really strict programming. Relatively strict programming if compared to different single page application frameworks. But let's say if you would forget but enable the flag angular will ask you, hey, maybe you want to get rid of some bugs andor while writing your code. And that's the only one frameworks which will do it Svelter. Svelter doesn't mean anything. We just go through to config which is in the package, which is in the hidden, let's say. But if I open this, then I can only see stricter as false. I think Svelte still has to do a little bit more in the typescript ecosystem. So while seeing this thing, I can see, okay, svelte is maybe not the best place, not the best framework to kick off with typescript and here we have a comparison. Angular has enabled on or off strict. I meant only the strict per se. React and view also can have it on the linters. I name it Linter. It's according to those, let's say old fashioned how to say, let's say the extra stick rules. Angular has two react, one certain view, zero to wrap up types helps preventing bugs. It's not only Reddit or Stag, overshore or any other source. Those is actually scientific fact. So it helps to. In this research it was about 15%, but for example, think it was TypeScript 2.0. So it was quite some time back. And now imagine with a new typescript. And if you'd enable your stricter rules, that's one and two, if you'd enable all the strict rules, or at least half of them we went through today, then this number can go up. And this is what I actually really like saying, that you don't need types because you are an expert. It's the same as you saying you don't need tests because you don't write bug code at the end, maybe a very little note. I cannot imagine there were that many bugs at Airbnb, but apparently they have made kind of audit. If they introduce typescript, then the bugs will be reduced by 38% of the bugs could have been gone. It's a big number. It's a big number. And I'm really curious if they enable the stricter rules or even if they restrict it. So we can maybe see that in the research they didn't. And here they did some and we can see, kind of approximation, how our code can be improved. That's it. That's again the QR code. If you want to connect me, just hit me up. I'm really happy to hear some feedback and walk a little bit more in depth in some of them. Thank you so much. It was a pleasure to give this talk.
...

Daniel Danielecki

Software Engineer @ Capgemini

Daniel Danielecki's LinkedIn account Daniel Danielecki's twitter account



Awesome tech events for

Priority access to all content

Video hallway track

Community chat

Exclusive promotions and giveaways