Converting a React App to Typescript
By: Jayson Alzate
Tags: Programming, JavaScript, Web Development, Typescript, React

Converting Our App to TypeScript

We can now begin using TypeScript by renaming our existing files to use the TypeScript file extension. Let’s start by renaming our entry point to index.ts from index.js . Also, remember to make sure to update your entry point in webpack.config.js .

After you make your update remember to kill your server and restart it. After you make the change, you should see the following:

Rule: You can only use JSX in files ending with the .tsx extension, not the .ts extension

Since our index.ts file uses JSX syntax, the compiler fails to recognize it. It will only recognize JSX in files ending in .tsx . If we rename our entry point to index.tsx , the app works. By contrast, if you try renaming your cart.js to a .ts file, you will encounter no problems with your build since JSX is not used.

Understanding Types vs. Interfaces in TypeScript

TypeScript does have a degree of type inference, but for the purpose of learning, we will manually type our application.

There are two ways to define types: interfaces and types. They have a number of differences. You can use what you prefer, but Microsoft generally recommends the use of interfaces where possible.

In general, interfaces are useful for objects. They allow you to denote the shape of the data you are using.

Types (or type aliases as they are known) are, in my opinion, better for functions and individual properties.

Below are two videos with some more information on differences and possible approaches.

Good overview video

In-depth comparison of Interfaces vs Types in Typescript. Optional but great video!

Adding Types to Plain JS Files

In this section, we will begin adding types to our project. We will focus on adding types to our files not containing JSX like our utils file.

I like to centralize the location of our type definitions so they can be easily imported and reused. We will first add a types folder in our src directory. Once this is done, we will take a look at our product.js file in our constants folder. As you can see our product information is an array of objects with a number of properties like id, quantity, etc. Below is an example.

Let’s now create an interface that defines the expected properties of a product. Let’s create a file called product.ts in our types directory.

Once we have created the file, let’s write our first interface. Below is the declaration.

Our first Interface !— Defined in types/product.ts

Now that we have defined an interface, let’s use it in our application! Let’s type our list of products using our interface. This is located in constants/product.js .

Our first step is to rename the file to product.ts to unlock the power of TypeScript.

Next, we have to import our Product interface. We will then annotate our list to denote that its type signature is an array of Product .

Here is a look at what our updated file should look like. We have added in some comments as well.

Annotating our list of products using our Product interface

After making this change and starting the app you should see … an error!

Reason — ”description“ property is not a part of all our products

We can fix this by making the “description” property optional.

Additionally, we can also define a ProductList type. We will head to our types/product.ts file and update it with the following code.

Our updated product type declaration file

Upon restarting the app, it should now correctly compile. If you want you can also replace Product[] with our new ProductList type. In the next section, we will take a look at typing functions.

Adding Type Signatures to Functions

In this section, we will be typing our cart utils file. This file is responsible for calculating the total of our cart. As always our first step is to rename our cart.js file to cart.ts .

We should note that this file uses lodash. If we want to leverage the type safety that TypeScript allows us, we need to import type definitions for lodash. These definitions will let the compiler know what types our lodash functions expect as arguments and what type they return.

Instead of having to manually type these functions, there is a project on Github named DefinitelyTyped. There are a large number of type definitions for a ton of different common packages. Let us first install the types for lodash with the below script.

Installing type definitions is as easy as an npm install for most popular packages

Let us now import our product types that we defined. Let’s now type our first function to calculate the total cost of a product. We will see two approaches to do this: inline or predefining a type alias.

Type annotating our function in-line.

Type annotating a function using a pre-defined type alias

Whichever approach you use is up to you.

I like to use inline typing generally if the function is not reused. This allows the typing to sit next to the logic, functioning as documentation.

I usually use the type alias approach for functions that are passed as props or reused. We can now continue to type the rest of our file.

Below is our fully typed file.

Our fully typed cart util file

Adding Types to React Components

We will now begin to look at adding types to our React component. First, let’s install the type definitions for the React libraries that we are using. We can do so with the below script.

We now want to rename our component files to the .tsx extension. After we rename our files, we want to restart our server. You should then see the following error.