React + TypeScript ❤️: The good parts ⚡
Tags: react, typescript, javascript, vscode
Published: 2020-09-08 15:56:46

I've started using [TypeScript](https://www.typescriptlang.org/) with [React](https://reactjs.org), and after a while, learning, and implementing them together. This is how I feel: 

{% twitter 1038372714170470400 %}
I couldn't believe how much my DX has improved. I'll leave you the main features I enjoy the most so hopefully you will feel excited to give it a shot 😃 !  

## Disclaimer ⚠️
This is not a beginner-friendly introduction to TypeScript, you need to know at least how to use [Interfaces](https://www.typescriptlang.org/docs/handbook/interfaces.html), however, at the end of the article I will drop a list of great resources I found very useful along with the fastest way to get React + TypeScript up and running and start hacking:
```bash 
$ npx create-react-app my-app --template typescript
# or
$ yarn create react-app my-app --template typescript
```

## TLDR;
Pros:
* Code completion and type validation with [type definitions](https://github.com/DefinitelyTyped/DefinitelyTyped).
* Great community and learning resources.

Cons: 
* TypeScript syntax and concepts like [Generics](https://ts.chibicode.com/generics/) can be hard to understand.

## Table Of Contents
  * [IntelliSense](#intelliSense)
  * [Type Declarations](#type-declarations)
  * [Type Validation](#type-validation)
  * [Hooks](#hooks)
  * [~~The Bad parts.~~ Trade-offs](#trade-offs) ⚖️
  * [Resources](#resources)
  * [Conclusion](#conclusion)

### IntelliSense <a name="intelliSense"></a>
I use [VSCode](https://code.visualstudio.com/) and one of its best features is [IntelliSense](https://code.visualstudio.com/docs/editor/intellisense) (A.K.A Code Completion), TypeScript takes advantage of it.
Let's say we have a simple `List` component, and we declare the `Props` Interface, in this case one prop `labels`, an Array of strings:

```jsx
// List.tsx
import React from 'react';

interface Props {
  labels: string[]
}

// We tell TypeScript the parameter type 
// + Object destructuring 👇
function List({ labels }: Props): React.Element {
  return (
    <ul>
      { labels.map((label, index) => {
        <li key={index}>{label}</li>
      )}
    </ul>
  );
}

const strings = ['React', 'TypeScript', '❤️'];
<List labels={strings}/>
```
#### This is what we get:
![IntelliSense](https://media.giphy.com/media/WOg7qdA8bRrWutWH9Z/giphy.gif)

If we type `labels.` inside `List` we get the code completion with methods and attributes from `Array.prototype`, in this case [Array.prototype.forEach()](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/forEach) and then inside the `callback` function  we get all methods and attributes from `String.prototype`, in this example [Array.prototype.toUpperCase()](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/toUpperCase).
VSCode is written in TypeScript, it has a built-in type definitions for Native Objects, and the best part? We can declare our own types, and most libraries we use come along with their own type definitions files already 😃 ! 
Which bring us to the next great feature: 

### Type Definitions <a name="type-definitions"></a>

React and TypeScript community is awesome, they've created a huge centralized repository of High Quality Type definitions files: 

{% github DefinitelyTyped/DefinitelyTyped no-readme %}

Most libraries keep their type declarations files on this repo, and sometimes we have to install them independently, on the [official website](https://www.typescriptlang.org/dt/search?search=) we can search and find instructions to install them, in the case of React, for example: 
```bash
$ yarn add @types/react --save-dev
```
How can we use them?
```jsx
import React from 'react';

interface Props {
  labels: string[]
}

function List({ labels }: Props): React.Element {
  const styles: React: React.CSSProperties = {
    backgroundColor: 'blue'
  }
  // ...
}
```
Let's say we want to write some inline CSS, in this case we can use the React built-in type definition `React.CSSProperties`, it'll show us an error if we write a typo like `backgroundKolor` and we'll get code completion for the properties 😁.
And we can also see the [source code](https://github.com/DefinitelyTyped/DefinitelyTyped/tree/master/types/react) so we get used to read and write them.
We already learned how take advantage of type definitions to get Code Completion, but now we'll learn another powerful feature that comes with them:

### Type Validation <a name="type-validation"></a>

What if we either don't pass the right prop type or we don't pass it at all?

```jsx 
interface Props {
  labels: string[]
}

function List({ labels }: Props) {
 // ...
}

const strings = ['React', 'TypeScript', '❤️'];
const numbers: number[] = [1, 2, 3];

// 1) We pass an array of numbers
<List labels={numbers} />
// 2) We don't pass it
<List />
```
In both cases we get an Error 🚫:
![Alt Text](https://dev-to-uploads.s3.amazonaws.com/i/rqjue2d91becfl70jgx6.png)

These errors are clear, they tell us what's the `type error`, where that `declaration` was made, if the prop is actually required, and this applies to functions also (although React Components are just functions 😉).
The TypeScript compiler won't be happy until we pass the right parameters, this is useful to see possible bugs ahead even before compiling the code and checking the browser.

#### What about [prop-types](https://reactjs.org/docs/typechecking-with-proptypes.html)? 

Yes, we can achieve the same validation using `prop-types`:
```jsx
import React from 'react';
import PropTypes from 'prop-types';

function List({ labels }) {
  // ...
}

List.propTypes = {
  labels: PropTypes.arrayOf(PropTypes.string).isRequired
}
```
However, since `prop-types` checks our code during runtime, we have to compile it first, see the actual error on the console, and also, this validation just happens on development mode 😟, whereas TypeScript analyses our code statically.

### Hooks <a name="hooks"></a>

When it comes to [React Hooks](https://reactjs.org/docs/hooks-intro.html), `useState` for example, TypeScript can be super handy, specially with type validations.

```js
function Counter() {
  // we can also use brackets <> syntax for types declarations:
  const [counter, setCounter] = useState<number>(0);
  const add = () => {
    // this is gonna give us an error 😱
    setCounter('string');
  }
  return(
    <div>
      <button onClick={add}>+</button>
      {counter}
    </div>
  );
}
```
In this way we make sure every time we update the `state` we preserve the value type, this can save us hours of debugging and headaches. 

### ~~The Bad parts.~~ 🤐 Trade-offs <a name="trade-offs"></a>

We learned how TypeScript can benefit the whole team when it comes to write components, just let's imagine we write our (ideally) reusable components library with well defined types and our colleague import one of them, they are gonna see beforehand:

* Props types and if they are required or not.
* Code completion for prop names.

This can save us time browsing source code to make sure we pass the right data to every component.
But we also know that in Software Development there is no Silver Bullet. Every tool we choose comes with a trade-off, in the case of TypeScript, of course there are some:
#### Reading TypeScript can be hard: 
```typescript
interface Array<T> {
  concat(...items: Array<T[] | T>): T[];
  reduce<U>(
    callback: (state: U, element: T, index: number, array: T[]) => U,
    firstState?: U
  ): U;
  // ···
}
```
But don't worry, I got this snippet from this [great article](https://2ality.com/2018/04/type-notation-typescript.html) which explains every detail, that example was really confusing for me at first.

#### Some concepts can be complicated to grasp: 
* Interfaces.
* Generics.
* Interfaces vs Types.

These new concepts (especially if members of our team aren't used to them) can bring more questions and confusion.
Of course we can tackle them, it just depends on our team members experience, available time, and feeling eager to learn new things.
This article reflects the idea I've been thinking about for a while and it's likely to be my next post topic, `everything in Software Development is a trade-off`: 

{% medium https://medium.com/@dan_abramov/you-might-not-need-redux-be46360cf367 %}

### Resources <a name="resources"></a>
These are the best resources that helped me to understand and love TypeScript:

* {% youtube Z5iWr6Srsj8 %}
* [Understanding TypeScript’s type notation](https://2ality.com/2018/04/type-notation-typescript.html)
* {% github typescript-cheatsheets/react-typescript-cheatsheet no-readme %}
* [TypeScript Tutorial for JS Programmers Who Know How to Build a Todo App](https://ts.chibicode.com/todo/)
* [TypeScript Generics for People Who Gave Up on Understanding Generics](https://ts.chibicode.com/generics/)


### Conclusion
![responsability](https://media.giphy.com/media/MCZ39lz83o5lC/giphy.gif)
TypeScript comes with a lot of benefits and constrains, but our context (team, priorities, goals) can define if we can get more advantages than cons and make our lives easier!
IMHO when it comes to large scale applications, and specially if we are building a bullet-proof architecture or System Design, the effort pays off, we can write less bugs-prone code and deliver features faster, and safer.

Thanks for reading, if you found this article useful please follow me on [Twitter](https://twitter.com/muydiego) and let me know what you think!

Happy coding!