React+Typescript is considered as one of the most popular bundles for creating client-side applications. This combination has a huge potential and allows to develop solutions of any complexity. In this article, we’ll see why
Typescript is so hyped, discuss some basic examples of working with components, storages, and API queries, and see the benefits of
Table of contents
- Project creation
- Props of Typescript
- Const of Typescript
I assume that all readers know about
React. Otherwise, it is pointless to proceed reading the article. To enthusiastic non-reacters please go to read the doc and then come back here.
TS helps us to fix most bugs and provides us with powerful tools to improve code quality. You can read more about the pros and cons of
TS in other articles, but we’ll go over them a little bit.
The goal here to so understand how
TS works within the
React , and what are the pros and cons of
TS and when we should use it.
So, we should start with creating a project. To create a simple
React+TS project, I recommend using the
create-react-app utility with the
$ npx create-react-app <project_name> --template typescript
After that, you will have a
React project ready to run, in which
TS support is already configured, and you can immediately start writing code.
Let’s introduce a small
Button component, which contains the following logic:
- Handles clicks
- Saves and displays the number of clicks on the button
This simple component, without using
TS, will be written like this:
And here we already have several problems:
- If we don’t pass a function to the component in the prop
onClick, or pass a different type of data there, the component will break at runtime (in the
handleClickfunction), which you might not notice during development.
- In the prop
textwe can pass any value, which could lead to unexpected output.
Most of the problems are due to the fact that we don’t know what types of data come to us in props. This problem is partly solved by the
propTypes library, but it has its own limitations — it can only type the component’s props.
TS allows you to cover everything with types:
onClick function, additional helpers and utilities, stores, and etc. An example of the same component, but using
So, let’s look at the changes. First, we have described the interface for the props. The interface for props is always called IProps. This interface describes the types of props our component accepts. In this example, we described that the component accepts the function
onClick: (event: React.SyntheticEvent) => void and the string field
To connect our interface to a component we use the generic type
React.FC, which takes our props interface as an argument
We also type the
handleClick function by describing that it accepts an event with the type
Now when we use the component we’ll get an error every time we don’t pass the required parameters (
text) and this will prevent us from compiling the project.
TS allows you to avoid simple errors with data types that pass through your application and also allows you to structure and strictly define input and output parameters of your functions (Components, Stores and everything else)
In addition to working with components, we often encounter stores. Basically, most of the projects use
Redux as a centralized data store. In this section, we will take a look at an example of a small
Redux store on
For example, we have a Reducer, which is responsible for our counter (from the component example) and has some actions (
I intentionally did not divide the code into several different files, although usually in a real project you keep the code divided by entities: reducer.ts, interfaces.ts, actions.ts, sagas.ts (or epics.ts).
In the first section, we declare
TS is ideal for this. Enum type — is a data type consisting of a set of named values called elements, members, enumeral, or enumerators of the type. In our case, we use an enum to declare the availability
actionTypes for this reducer. The declaration of
actionTypes is usually found in the file
Then comes the declaration of the types and interfaces we need for the reducer. In this example, I’ve added the
BaseAction<ActionTypes, Payload> interface, which is not usually located directly in each store, but is a common interface used for all actions and is usually separate(for example, in the file
store/interfaces.ts). Then comes the declaration of the interface, which describes the state of the reducer. In our case the reducer stores only one field:
value: number . Also, we declare the
CounterPayload = number type for payloads of all actions that work with this reducer. Finally, the last type is
CounterAction, which uses a generic
BaseAction interface with the necessary parameters. All information about types is usually in the file
interfaces.ts, but it can also be stored next to entities (
The next section is a simple declaration of action creators. These are simple functions that return actions. Thanks to the typing (
CounterAction) we keep all action creators looking the same.
And, finally, the reducer:
In the Reducer, we actively use all the types and interfaces declared above. We use the
CounterState interface to create
initialState, and we use state:
CounterState = initialState and
action: CounterAction as parameters for the reducer. That way, we can’t use something that we didn’t declare in our interfaces. For example, you can’t add a new field to a state without updating the
CounterState interface; after adding it, you’ll have to refactor the cases where the new field isn’t returned and
TS will tell you where and what might be broken. Or, for example, you can’t add a new case to the reducer until you add
actionType to enum
CounterActionTypes. This allows us to make our code robust and bug-proof and protect developers from primitive bugs when working with code.
Working with API
It is also desirable to write interfaces to work with the
API. Usually, it’s very convenient to describe the
response’s interface. And if your server is written in
TS, then you can once describe interfaces for
reponse’s and use them both on the server and on the client. It’s very convenient. Small example of working with
- Reliability. TS allows you to make your application much more robust. You no longer have to worry about calling a function or accessing an object field — typescript will tell you if you made a mistake and won’t let you compile code with an error.
- Easy refactoring. You almost never have to worry about breaking something while refactoring. TS simply will not allow you to break the code.
- IDE support. TS allows you to take autocomplete in your editor to the next level and make it similar to autocomplete in more complex languages(C, Java). Autocompletion, auto-imports, error, and problem highlighting on the fly — all this makes Typescript a great tool for development.
- Patterns. Typescript is a full OOP language that allows you to write OOP-style code. TS implements some useful features, which do not exist and most likely will never exist in native JS. For example, in TS you can use class access modifiers (public, private, protected), decorators, and Dependency Injection. So, if you use TS, you’re getting much closer to popular patterns of modern development than using native JS. Of course, most often these patterns are not applicable to Frontend applications, but some of them are actively used, for example, in Angular. But React also actively uses the advanced features of TS.
- A Large community. Typescript is a mature technology with a huge community, and if you have a problem, just google it and chances are someone has already solved it.
- Open-source. 95% of the libraries and third-party modules are written in Typescript and you should have no problem using them.
- Learning assistance. TS allows you to learn in more than just JS, because it implements many approaches from other languages. If you know and can use Typescript well, it will be much easier for you to learn and use other languages in the future.
Pros of TS
In this section, we will consider all the advantages of
React and highlight the main thesis — why and when to use
TS together with
If you are developing or planning to develop a large project with long-term support — TS is your go-to choice. Of course, you can also hard-code in TS, but the language itself regularly punishes you for writing bad code. TS will protect you from the primitive bugs and errors and add confidence to your project. But, don’t forget that typescript helps only at the development stage. After compilation, it completely disappears and runtime works in JS with all its advantages and disadvantages. If you’re looking for code quality and have enough time to learn and implement the technology, Typescript is your choice!
If you choose to use Typescript but exclude unit testing from the workflow, this is a very bad pattern. It’s always better to choose tests over Typescript, because Typescript tests your code, but tests check the business logic, which is much more important!
- You will have to write a lot of code. On TS you will have to write a lot more code. The amount of code in TS is usually 1.5–2 times higher than in native JS. Accordingly, the time you will spend on the tasks increases proportionally by 1.5–2 times. This is the price for reliability. You have to describe new types and interfaces over and over again and be able to apply them correctly. You’ll also have to spend some time studying the interfaces of external libraries and third-party modules in order to correctly integrate them into the project.
- TS is not for beginners. If your project is planned to be developed by beginner developers (Interns, Juniors), TS is probably not for you. It has a rather high entry threshold. In addition to the complexities of JS, developers will also have to learn the intricacies of Typescipt, which is likely to be very difficult for them.
- You still can write bad code. Yes, this is bad. If something doesn’t work, you can always use //@ts-ignore or any , but by doing this you create problems for yourself in the future. And if your project doesn’t have strict conditional rules described in tsconfig or eslint (for example, don’t use any , cover everything with types), you won’t benefit from TS.
- You will have to declare types for libraries. Even if you don’t have to do it that often, it is quite hard. Especially when the library is not a simple utility, but a whole set of utilities. Fortunately, these days there are almost no untyped libraries left (thanks to DefinitelyTyped)
- Transferring a large production project to TS is difficult. We have tools for that, and you can transfer the project gradually, but all the time you’ll be in pole position and won’t be able to take full advantage of TS. And if you’re also developing features at the same time, the move to TS can drag on for quite a long time.
TS Pros and Cons
But, as we all know, there is no silver bullet and
TS also has its disadvantages:
TS is definitely not the right choice for you:
- If you don’t want to write in it or you’re having a hard time writing code in it.
- If your project’s goal is to release the product as soon as possible (
TSis also not the best choice for you. You can write the basic version using
JS, and once the product finds the market fit, rewrite everything using
- If you have a lot of Junior developers, you may have a problem with TS and you probably shouldn’t use it. At least, you should definitely start with a small one.
- If you already have a big working project in
JSand you’re planning to rewrite it using
TS, most likely it’s not worth it. You’d be better off improving your current project code and covering it with tests. This is much more important.
- If you have the opportunity to write a type and not use
any— do it.
anycontradicts the main principle of TS — reliability, and exists only to transfer large complex projects to
TSgradually. And even in that case, it’s better to try not to use
any. If possible, try to never use any ever.
In conclusion I would like to say that
TS is a great tool, which is becoming more and more popular every year. And with
React it allows you to add the very reliability and transparency, which are usually missing in Frontend applications. In large corporations,
TS has long been a must-have, but gradually it becomes a must in smaller companies, and hence the number of developers who can use
TS is increasing. Just try learning and using
Typescript on a project and you’ll realize how cool this tool is.