introduction to the world of reliable programming

Let's talk about an introduction to TypeScript and how we can use it to make our programming and our JavaScript code more reliable and predictable.

My name is Alexander Chernov, I am a front-end developer at Alpha, I host the podcast “TINOID“, I love swimming and am in love with web and front-end development.

Is everything good in the world of JavaScript programming?

Let's imagine that we have a simple function addwhich takes two parameters and performs addition or concatenation if we pass strings.

In the example, we pass numbers and expect that the program will not break and everything will be fine, we hope and pray.

Let's output the result to the console – we get 3. Everything is fine, no errors, the program works as expected.

Let's see what happens if we hover over the function and look at the tooltip from the IDE.

The IDE says there is a function here addwhich takes parameters a And b and returns something. And this “something”, the so-called designation, is signed as any.

In the context of the example any says that our function add and our development environment understands that we can pass anything here because any is the absence of a specific type. Even if we don’t transmit anything, we won’t see any error, because we haven’t specified anything specifically.

In the next example there is another function – double:

We expect to accept parameter a, but when we record the execution of its result (on line 5), we do not pass an argument.

In fact, we should get an error saying that we are expecting something from the function, but are not passing anything. But since the designation type anythen our function will not complain that we forgot something, even if we leave the arguments empty.

And, naturally, we will see this error only when we launch the program, which we will then need to find and debug. This complicates the development process.

And even if we expand the arguments and pass something else there, our function, of course, will work with the first argument. But, nevertheless, why do we need the rest, what if we break something? And it will be very difficult to debug such an error, especially when we expect that the code is written correctly.

JSDoc

To make writing in JavaScript easier, developers came up with such a thing as JSdoc. This is a special decorator with which we can describe our functions. Allows you to create descriptions for functions, as well as parameters and return types.

Accordingly, to describe any parameter, we need to include the following construction:

  • Describe in param what we expect to receive, an argument, and the type of that argument. In this case the argument a type number.

  • IN returns we write that we will return. In my example, we expect that we will also return some number.

  • And in description We describe what it is: how to work with the function, how we can use it.

Let’s imagine that we have described everything, made an npm package, and another developer will import the function and use it. But what if he didn't read the description and will use three arguments in the same way, as we tried earlier? If a developer reads the code as described, but wants to go a different route, nothing will stop him from doing so. In this case, we will not see the error again at the coding stage.

In other words, JSdoc will not save us from finding errors during development.

Smoothly approaching TypeScript

Programming languages ​​can be divided into two categories: dynamically typed and statically typed.

In programming languages ​​with dynamic typing, like JavaScript, at the writing stage we do not know how and with what data our program works and what types this data has.

In statically typed languages, TypeScript, code is checked for correctness/errors before the code is run.

TypeScript is a superset (extension/add-on) of JavaScript that adds (software) types.

TS is the same JS, but with types.

Types are a set of values ​​with which we can describe our variables and functions. Types in TypeScript are used to define and describe data that can be defined and used in a program. We can use value types like number, boolean, string and so on.

I won’t theorize for a long time, I’ll go straight to an example.

How can TS help us?

To use TS, we need to add the package to our project and initialize it.
npm i typescript -D / npx tsc --init and be sure to change the file extension to .ts
After this, our TypeScript is put to work. Of course, it requires a little more configuration, but here I have intentionally simplified the process.

And as soon as we look at our code from the previous example with the function doubleTypeScript throws an error.

We see that our parameter a In fact any: we can transmit anything, or we can not transmit at all. This is a bug for TypesScript. But the main thing is that we see it right away – at the stage of writing code. And we can immediately understand where we made a mistake and how to correct the mistake.

And we won’t be able to simply call our function with empty arguments, because we need to explicitly indicate something: we expect one argument to be passed there, but we pass zero – this is an error.

Let's see an example of how we can type our function double.

We assume working with numbers, so we can describe the type number at the parameter a. The return type will also be numbersince we expect to receive exactly this at the output.

And now when we call our function, if we turn to the prompts of our IDE and hover the mouse over the function call doublewe will see that she is clearly no longer expecting anyand type number y argument, and we will also return number.

Thus, we have typed the function. If we try to pass there, let's say, the type string arguments, or make more of them, or not transmit them at all, as in the previous examples, then we will immediately receive an error, which, after all, will protect us from this.

Where else can we use TS? Let's consider one typical task.

Using TypeScript with the API

Let's look at an example of receiving data from some endpoint and displaying it in our layout. The illustration shows an example in JS (React).

Here we create some state that will store an array of our users. IN useEffect we make a request to the endpoint, and then conditionally return our user array in JSX markup.

When I write an attribute key I would like my IDE to tell me what fields I can use on my user. If I try to call the tooltip in this example using a JSX extension without TypeScript, then, unfortunately, I will not get anything useful: some system messages and types will appear that will not help me in development.

How can this be fixed? First, we need to refer to the documentation of our backend and find out what types and JSON we can receive from our endpoint. This can be done using Swagger / Descriptions in the documentation or the tools that you use in the team, or just go to the endpoint and see what JSON we receive.

In this case we see that we have an array of objects user with certain fields that we definitely need to get.

Let's take a couple of them. For example, for the attribute key will suit us id and let's say the name name.

In order to type our component we need, naturally, to change the extension to .tsxand then create a special type User. And describe it in this syntax.

We explicitly indicate that our type User will contain id with type number And name with type string:

After this, we can immediately type our state. To do this, let's tell him that now he can accept not just a certain null (as the initial value), but must also take into account that the type can come eithernull if the request fails, or an array of objects with the user type, which we described above.

Please note that now when you try to call a tooltip, it is already clearly visible which fields can be used in the attribute key. These tips will just work with our list of users. If we expanded them, we would see more fields there that could be used.

This is how we increased the speed of development, and if we do such generation automatically (or even manually), then we will not be able to use extra fields that can lead to errors undetected.

About d.ts files

It also happens that we have typed our code, but then use someone else’s untyped API module/component. This is a fairly common problem, especially if we use some unpopular library to solve it. There is a solution here – d.ts files. Files with the .d.ts extension contain type declarations for TypeScript, which contain descriptions of types without implementation. They allow the TypeScript compiler to understand the structure of data, functions, and classes that were not written in TypeScript (such as JavaScript libraries).

Using TypeScript with Props

Another common case is the use of TypeScript in the context of props.

I think many people know the pain of forgetting to write props (if this is an expanding project, and you always need to keep them in mind). And TypeScript helps you type props and not forget anything.

For example, I want to describe some props. I will expect that in my component UsersList I will pass some header like header. For this purpose I describe a special type Props and I tell him that it will contain a field header with type stringthat is, a string. I also use this type in the description of the type Props already in the component itself.

And then, when I use the component in my markup, I will see the error below in the component when writing the code.

I don’t need to run the program or keep in mind the props that I would like to use – I can “forget” to write them, and with TypeScript I will always see an error and can correct it. Comfortable. The main thing is not to forget to describe the props!

Let's summarize

As a front-end developer, I strongly believe that TypeScript is an indispensable tool for creating scalable, reliable, and easily maintainable web applications. Static typing improves code quality and development productivity in the long run. Here are some pros of TypeScript:

Potential errors are visible immediately – at the coding stage. This, naturally, significantly reduces the time (almost completely in some cases) for debugging. For example, if I try to assign a string to a numeric variable, the TypeScript compiler will immediately report an error.

Code readability. Clearly defined data types make the code more understandable both for me and for other developers working on the project. This is especially important when working in a team or on long-term projects. It becomes easier to dive into the project and understand what the data flow is and what we do with it. It is quite difficult to quickly “enter” large JS projects, but TS helps with this too – you see what data is received by which component, and you can build a logical chain. In “pure” JS, everything is up in the air.

Using AutoCompletions in the IDE. The intelligent autocompletion and refactoring provided by modern TypeScript-enabled IDEs significantly speeds up the development process. I can quickly create new code and change existing code without fear of making mistakes.

More reliable APIs. TypeScript helps you create more reliable and predictable APIs, both within a component and between components. For example, I can clearly define the type of data that a function accepts and returns, which minimizes the risk of unexpected errors, and other developers can just as quickly understand what is being returned to the server and what can be done with it.

If you need static typing, if you want to understand your application more, have more reliability, then I recommend it. Yes, of course, starting a project using TS is not so fast (although now there are a lot of tools for TypeScript, a large number of automations), but it is definitely a good investment in the project!

True, if you decide to implement TS on a project that has been working for many years and is already supported, then perhaps it is not worth spending resources on adding TypeScript. Here the business will decide whether it is profitable or not. And developers can use, for example, JSDoc.

I can recommend the following materials for learning TypeScript:

And also excellent online trainer with the ability to select the difficulty level:

Similar Posts

Leave a Reply

Your email address will not be published. Required fields are marked *