Using Typescript in React: a Crash Course
Tags: webdev, javascript, react, typescript
Published: 2022-06-27 20:36:10

by [Ajibade Ola-Oluwa](https://blog.openreplay.com/authors/ajibade-ola-oluwa)


[Typescript](https://www.typescriptlang.org/) is a strict superset of the Javascript programming language, extending Javascript with new features and syntax. 

Typescript is like a built-in unit test and gives us the benefit of the compiler watching our back, prompting errors even before the code is run, and adding static and robust typing to our applications. 

This article is a quick guide to get you started and comfortable using Typescript in React, creating simple use cases with Typescript. You'll need an [understanding of React](https://reactjs.org/docs/getting-started.html), familiarity with [Javascript Types](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Data_structures), and basic understanding of [Node](https://nodejs.org/en/) and [npm](https://www.npmjs.com/).

## What is Typescript?

Typescript is an open-source programming language created by Microsoft, and it was designed to develop large applications by adding static typing controls to JavaScript. It may be used to develop applications for both client-side (web-browser) and server-side (Node.js or Deno). 

In simple terms, Typescript is Javascript plus static typing features whenever you want them. The idea of having static type checks in Javascript is amazing; that is one reason why the use of Typescript is rapidly increasing.

## Why do Software Companies prefer to use Typescript?

The use of Typescript has soared compared to the last six years ago, according to several rankings like [this](https://octoverse.github.com/#geographical-distribution-of-active-users), [this](https://insights.stackoverflow.com/survey/2021#technology-most-popular-technologies) accounts.

Using Typescript (instead of Javascript) makes it possible to remove certain software anomalies earlier during the development phase and secure the code before going into production.

Typescript also makes it easier to reuse code and manage types and special cases, which the development team would not have thought of easily. It forces the team to take these topics into account, and as a result, best practices are encouraged, saving development time and reducing the frequency of bugs.

Learning Typescript is worthwhile when a team is more concerned about security. Typescript type checks codes at compile time, detecting possible issues before they become vulnerabilities, making it easier to trace application errors or weaknesses. 


##  Adding Typescript to React

To create a new React project with Typescript template append  
`--template typescript` to the `npx create-react-app` command. 
Run this on the terminal; it creates a new react app called `my-app`.

```
npx create-react-app my-app --template typescript
```

Using this command, the directory structure can be viewed as:

![Directory structure](https://blog.openreplay.com/static/22fdd99169f006f5635bb2e2e7252d0a/daafc/image01.png)

Run `npm start` on the terminal, to test that everything is working.

## How does TypeScript compile React code?

Open the project directory in your preferred editor (I'm using [VSCode](https://code.visualstudio.com/) here). You will notice a `tsconfig.json` file. This is where the magic of Typescript happens. Typescript looks for the `tsconfig.json` file in the project root folder, and that file provides configuration options for the compiler. 

Typescript compiles our React code to type-check it. The [v8-engine](https://v8.dev/), which is the program that executes Javascript in the browser, does not understand Typescript, so [transpilation](https://en.wikipedia.org/wiki/Source-to-source_compiler) is needed. 

To run our app, Typescript is converted into plain Javascript by the Typescript compiler ([tsc](https://www.typescriptlang.org/docs/handbook/compiler-options.html)). The compiler goes through the `src` directory in our project and converts all `.ts` files into `.js` files. By default, it ignores files not in the src directory, but this default configuration can be modified in the `tsconfig.json` file.

## Understanding Types

Before we delve into building React applications with Typescript, let's talk about an essential part of Typescript, which enables its static type checking abilities. Generally, programming languages fall into two categories: **statically typed** or **dynamically typed**.
In static typing, types of variables must be known at compile time. If a variable is declared, the compiler must know the variable type. Some languages in this category are C# and Java.
In dynamic typing, the type of a variable is known only when the program is running. Python and JavaScript are languages in this category. 
Using Typescript converts JavaScript into a statically typed language.

What are types? They are labels that describe the different properties and functions a value has. Javascript has a number of built-in (primitive) types, all [accessible to Typescript](https://www.typescriptlang.org/docs/handbook/2/everyday-types.html#the-primitives-string-number-and-boolean): string, number, boolean, null, undefined, etc. Typescript also has some advanced types: 

- **void:** denotes the absence of any type.
- **empty type {}:** describes an object that has no property of its own.
- [**tuple:**](https://www.typescriptlang.org/docs/handbook/2/objects.html#tuple-types) works like an array,  but the number of elements here is fixed. The types of elements in a tuple are known and can be of different types.
- [**enum:**](https://www.typescriptlang.org/docs/handbook/2/everyday-types.html#enums) is a group of constant values that are closely related and known.
- [**any:**](https://www.typescriptlang.org/docs/handbook/2/everyday-types.html#any) allows us to assign the value of any type to a variable. Used when a value type is unknown
- [**never:**](https://www.typescriptlang.org/docs/handbook/2/narrowing.html#the-never-type) is a type that contains no value, so we can't assign any value to a variable with a never type.
- [**union:**](https://www.typescriptlang.org/docs/handbook/2/everyday-types.html#union-types)  this describes a value that can be one of several types `number | string | boolean`
- [**object type:**](https://www.typescriptlang.org/docs/handbook/2/everyday-types.html#object-types) To define an object type we list its properties and their types: `{x:number, y:number}`

## Type annotations

Typescript uses its type annotation to specify the type of a value (string, boolean, number, etc). Typescript uses the syntax `: type` after a value's identifier, where `type` is a valid type such as string, boolean, number, etc.

```jsx
let variableName: type;

let name: string= 'Jane';
const active: boolean= true;
let arrayName: number[] = [2, 4, 6, 8]
```

Once a value identifier is annotated with a type, it can only be used as that type. If the identifier is used with a different type, tsc will issue an error.

## Type Interfaces

Typescript interfaces are essential to enforcing a particular object shape. An interface is like an object; it contains information about the object's properties and types. An interface explicitly tells the Typescript compiler about the property names and the value types an object can have.

```jsx
interface Location{
 from: string;
 to: string;
}

function printCoord(holiday: Location) {
    console.log("We are going to" + from + "to" + to);
}

printCoord({from: "london", to: "new-york"});
```

After defining the `Location` interface, we can use it as a type. Here we annotate it to the function parameter to type-check the function arguments when called. 

There are several ways [typescript interface](https://www.typescriptlang.org/docs/handbook/type-inference.html) can provide type information in our codes.

## Type Aliases

Aliases allow us to create a new name for an existing type. Here a new type is not defined; we only create a new name for the type. It is common to use the same type more than once, so a type alias is a convenient way to give a new name to an object type declaration. 

Unlike an `interface`, `type alias` can also be used for other types such as primitives, unions, strings, and tuples. 

Type aliases and interfaces are somewhat similar. Type interfaces work better with objects and method objects, while Type aliases work better with functions, complex types, etc. 

For creating new type aliases, we use the `type` keyword.

```jsx
type Location= {
 from: string;
 to: string;
}

function printCoord(holiday: Location) {
    console.log("We are going to" + from + "to" + to);
}

printCoord({from: "london", to: "new-york"});
```

## Generics

[Generics](https://www.typescriptlang.org/docs/handbook/2/functions.html#generic-functions) help make the type system flexible and reusable. They allow us to generically define types that a function can return with, using type-variables such as `<T>`. `T` is a placeholder and can be changed to any other variable name.

Why do we need Generics? Let's take a look at a regular typescript function without generics.

```jsx
 function removeItemFromArray(
    arr: Array<number>,
    item: number
  ): Array<number> {
    const index = arr.findIndex((i) => i === item);
    arr.splice(index, 1);
    return arr;
  }

   console.log(removeItemFromArray([1, 2, 3], 2))         //  [1, 3]
```
Above, we defined a function that removes a specified number from an array when called. Assuming we need to remove a string from the Array, we would have to develop a new function.

```jsx
  function removeItemFromArray(
    arr: Array<string>,
    item: string
  ): Array<string> {
    const index = arr.findIndex((i) => i === item);
    arr.splice(index, 1);
    return arr;
  }

 console.log(removeItemFromArray(["red", "green", "blue"], "green"));      //  ['red', 'blue']
```

The logic for both functions is the same. Later we may decide to remove another value type (boolean, object...) from an array, and we'd need yet more versions of the same logic... but creating a new function each time we want to remove a value from an array doesn't scale.

One solution is to use the 'any' type; to do this, we need to set the type of the array argument to `any[]`. But the drawback here is that `any` doesn't enforce the type of the returned element, which means it is not type-safe. A better solution to avoid creating multiple functions is to use Generics in typescript.

Using generic types to create a new removeItemFromArray() function would be as follows:

```js
  function removeItemFromArray<T>(arr: Array<T>, item: T): Array<T> {
    const index = arr.findIndex((i) => i === item);
    arr.splice(index, 1);
    return arr;
  }

  console.log(removeItemFromArray<string>(["red", "green", "blue"], "green"));
  console.log(removeItemFromArray<number>([1, 2, 3, 4, 5, 6], 3));
```
 
Here we can notice the function uses the type variable `T`. `T` lets us capture the type provided when the function is called. The function also uses the type variable 'T' as its return type.

Now our function can be used with different types. In the above example, we can call the function explicitly by passing a type(number, string, etc.) as generic to the removeItemFromArray() function.

## Conditional Types

Conditional type helps describe the relationship between types by using the `extend` keyword and selecting one of two possible types. Conditional types look like the [ternary operator](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Conditional_Operator) in Javascript (condition ?  trueExpression : falseExpression ). They work great with generics.

```jsx
someType extend anotherType ? trueType : falseType;
```
The syntax `someType extends anotherType` describes the type relationship between them. If this condition is met, the trueType is selected; else, the falseType is selected.

Example for Conditional Types: 
```jsx

interface Animal {
  adopt() : void;
}

interface Dog extends Animal {
  woof() : void;
}

interface Cat {
  meow() : void;
}

type Owner1 = Dog extends Animal ? boolean : string;    // returns boolean type

type Owner2 = Cat extends Animal ? boolean : string;    // returns string type
```

Here Dog extends Animal; therefore, it returns a boolean type, while the Cat interface is not extended to Animal. So for Owner2, a string is returned.

## Functional components 

A React Functional Component is a function that takes props objects and returns JSX elements. In React components, we need to consider the type of props coming in. We will be writing all code in the `App.tsx` file to make things simple to follow. Delete everything inside the function in that file and return the simple code below.

```jsx
import React from "react";
import "./App.css";

function App() {
  return <h1>Hello World</h1>;
}

//add "Employee" component .....

export default App;
```

There are several ways of creating a functional component in React using Typescript.

### Props Type as an Argument

This is one of the easiest ways to declare a functional component. First, we state the type using the `interface` or (`type`) keyword. Then annotate the `interface` object to the function props. The `interface` object explicitly states the props type and name.

Introduce a new component, `Employee,` and call it inside our App component above it.

```jsx
import React from "react";
import "./App.css";

//type declaration
interface MessageProps {
  message: string;
}

function App() {
  return (
    <>
      <Employee message="Hello" />
    </>
  );
}

// "Employee" component 
function Employee({ message }: MessageProps) {
  return (
    <>
      <h1>Welcome {message}</h1>
    </>
  );
}

export default App;
```

### Inline Type Declaration

Another way to create a functional component in React using Typescript is to inline a type declaration in the function component. This eliminates naming the props type but gets uncomfortable if the function component gets complex. Change the `Employee` component in the previous code to:

```jsx
// change "Employee" component 
function Employee({ message }: { message: string }) {
  return (
    <>
      <h1>Welcome {message}</h1>
    </>
  );
}
```

### React.FunctionComponent or React.FC

A common way of creating a functional component in React using Typescript is to import React's `FunctionComponent` or `FC` type; FC is just an alias for FunctionComponent. With this method, we cannot create the component using a function declaration, so we will have to use a function expression.

Change the `Employee` component in the previous code to:
 
```jsx
// change "Employee" component 
const Employee: React.FC<MessageProps> = ({ message }) => {
  return (
    <>
      <h1>{message}</h1>
    </>
  );
};
```

Using **React.FunctionComponent** or **React.FC** approach comes with some disadvantages:
- **Imply type of children**: React.FC provides access to props' children even when we don't want it. Our `App` function now accepts a `children` prop, even though we are not doing anything with it.
- **Type a function, not its arguments**: Using React.Fc types, we will have to annotate the function type itself. This means we need to use a function expression like an anonymous function assigned to a const/variable or arrow function when using React.Fc like in the example above.
- React.FC doesn't fit well with Generics.

React.FC can be helpful for beginners just getting into Typescript in React as it guides us with types. But it is not generally advisable to use React.FC [today](https://github.com/facebook/create-react-app/pull/8177) because of its disadvantages. 


## Open Source Session Replay

_[OpenReplay](https://github.com/openreplay/openreplay) is an open-source, session replay suite that lets you see what users do on your web app, helping you troubleshoot issues faster. OpenReplay is self-hosted for full control over your data._

![replayer.png](https://static.openreplay.com/images/banner-blog.png)

_Start enjoying your debugging experience - [start using OpenReplay for free](https://github.com/openreplay/openreplay)._




## Types for State and Props in React

In Typescript, variables, states, and props are limited to the types they are defined with; when we write our code. These types can be defined on the variable values using type annotations with primitive types, type interface, type alias, tuples, union, etc.

```jsx
import React, { useState } from "react";
import "./App.css";

interface IProps {
  staff: string;
  message: string;
}

interface IState {
  position: string;
  experience: number;
}

function App() {
  return (
    <>
      <Employee message="Good Morning" staff="Ryan" />
    </>
  );
}

function Employee({ staff, message }: IProps) {
  let [state, setState] = useState<IState>({
    position: "Software Engineer",
    experience: 17,
  });
  return (
    <div className="App">
      <h2>
        {message} {staff}
      </h2>
      <ul>
        <li>
          <span>Position:</span> {state.position}
        </li>
        <li>
          <span>Year Of Experience:</span> {state.experience}
        </li>
      </ul>
    </div>
  );
}

export default App;

```
Notice the use of `interface` to specify our state and props object types, and the type annotations used in the code. This is a typical pattern for type-checking state and prop values.

## Event and Input form handling

Here is a tricky one, how do we get to know or specify the type passed to an event on change or input? React provides many built-in event types that we can use to specify the type for all events. One easy way to tell the type of event to use for a particular event is to hover on the event handler (e.g., onChange, onSubmit, onBlur).

![Getting types for events](https://blog.openreplay.com/static/42dfa7d663e8614fa7f4da35fcde0ecf/aaf9a/image02.png)

Hover on an event, and you'll see the appropriate type for the event. Let's see a quick example of a form using the event type in react:

```jsx
import React, { useState } from "react";
import "./App.css";

type IProfile = {
  username: string;
  password: string;
};

function App() {
  const [profile, setProfile] = useState<IProfile>({
    username: "",
    password: "",
  });

  //Checking Event Type for onChange Method
  let updateInput = (event: React.ChangeEvent<HTMLInputElement>): void => {
    setProfile({
      ...profile,
      [event.target.name]: event.target.value,
    });
  };

  //Checking Event Type for onSubmit Method
  let login = (event: React.FormEvent<HTMLFormElement>) => {
    event.preventDefault();
    console.log(profile);
  };

  return (
    <div className="App">
      <h2>Employee Login</h2>
      <form onSubmit={login}>
        <div>
          <input
            name="username"
            value={profile.username}
            onChange={updateInput}
            type="text"
            placeholder="Username"
          />
        </div>
        <div>
          <input
            name="password"
            value={profile.password}
            onChange={updateInput}
            type="password"
            placeholder="Password"
          />
        </div>
        <input type="submit" />
      </form>
    </div>
  );
}

export default App;
```

## JSON Documents

Imagine a scenario where we are to work with a complex JSON object, like fetching an API and still having to use Typescript to type-check its data. This can be difficult; if possible, most programmers would rather avoid it. 

One quick and secure way of using types for JSON data (API response) is to convert them to Typescript interfaces using tools like [quicktype](https://app.quicktype.io/), [transform](https://transform.tools/json-to-typescript), etc.

![Getting types for JSON](https://blog.openreplay.com/static/f8e5336bfb024a180b854a1f9c71a6c5/ba06a/image03.png)

To use the tools above, copy and paste the API JSON object into the tool, and it auto generates the interface type for us. Let's see an example using  quicktype.io to convert our JSON data into types for type-checking:

```jsx
import React, { useEffect, useState } from "react";
import axios from "axios";
import "./App.css";

// Generated interface type from "quicktype.io"
interface User {
  userId: number;
  id: number;
  title: string;
}

function App(): JSX.Element {
  const [employees, setEmployees] = useState<User[]>([]);

  useEffect(() => {
    axios
.get("https://jsonplaceholder.typicode.com/albums")
      .then((res) => setEmployees(res.data));
  }, []);

  return (
    <div className="App">
      <h1>COB Summary</h1>
      <table>
        <thead>
          <tr>
            <th>Id</th>
            <th>Job Summary</th>
          </tr>
        </thead>
        <tbody>
          {employees.length > 0 &&
            employees.map((employee) => {
              return (
                <tr key={employee.id}>
                  <td>{employee.id}</td>
                  <td>{employee.title}</td>
                </tr>
              );
            })}
        </tbody>
      </table>
    </div>
  );
}

export default App;
```
## Promises

Another Javascript feature extended to Typescript is the [Javascript promise](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise). In Typescript, the return type of promise is defined immediately after the promise keyword, determining the data type of the value returned by the promise when it is resolved.

Since errors can take any shape, the default data type of value returned when the promise is rejected is set to `any` by Typescript. Let's look at the following example of using promises in React.

```jsx
const pickEvenNumber = new Promise<number>((resolve, reject) => {
      const isEvenNumber = Math.floor(Math.random() * 20);
      if (isEvenNumber % 2 === 0) {
        resolve(isEvenNumber);
        return;
      }
      reject(isEvenNumber);
    });

    pickEvenNumber
      .then((res) => console.log("Resolved: Even Number " + res))
      .catch((err) => console.log("Rejected: Not Even Number ", err));
```

In the above example, pickEvenNumber is a promise created using the promise constructor that resolves a number. The resolved data type of this promise is a number; hence tsc won't allow us to call the `resolve`  method with any other value except a number type.

## Conclusion

In this article, we used Typescript in React to create functions, states, props, promises, and much more. Understanding Typescript is definitely an ace up your sleeve in your developer career.  

For more in-depth knowledge on using Typescript with React, visit the [documentation](https://www.typescriptlang.org/docs/handbook/react.html). You can find the article's source code [here](https://github.com/ajibade3210/typescript-in-react).

[![newsletter](https://blog.openreplay.com/static/e6b18eda7a327511296a2f27692f9c70/e9957/newsletter.png)](https://newsletter.openreplay.com/)