How to Use Create React App With TypeScript

By Sruthy

By Sruthy

Sruthy, with her 10+ years of experience, is a dynamic professional who seamlessly blends her creative soul with technical prowess. With a Technical Degree in Graphics Design and Communications and a Bachelor’s Degree in Electronics and Communication, she brings a unique combination of artistic flair…

Learn about our editorial policies.
Updated March 10, 2024

Read this hands-on tutorial to understand how to use Create React App with TypeScript:

Create React App is an application generated by Facebook as a way to quickly get started on creating a React application.

Create react app is basically a node package that we can simply install.

The interesting part about this is that you can use it with TypeScript very easily by leveraging the use of npm or yarn depending on what your package manager preference is.

=> Check Out ALL The TypeScript Tutorials Here

Create React App TypeScript

Create React App TypeScript

Prerequisites

For this project, it is a prerequisite to have NodeJS and TypeScript installed on your laptop/system. You will also need an IDE of your choice.

As far as package management is concerned, we personally prefer npm, so we are going to use npm for this tutorial. But for a start, we are going to install the Create React App with npx.

Template Flag

The installation process will execute and generate the react application. We will give it a name and then we will specify the template and that template will be TypeScript.

The reason we have this template flag is to enable us to specify the type safe JavaScript language of our choice, for instance, if you wanted to use something like Flow, which is another approach of doing type safe JavaScript you would.

The flow was developed by Facebook to implement their internal stuff, but a lot more projects are going down the direction of TypeScript than they are with Flow.

Create React App

To view Create React App, open your terminal, navigate to your workspace directory and run the below command.

npx create-react-app app –template typescript

This is going to spin up just like any basic application and the resulting application is going to be what the React community has agreed upon, which is a create-react-app default template.

Next, when prompted “Okay to proceed? (y)” click y and then press the Enter key to install the package. Once the template has been downloaded, you’ll be good to go.

The Create React App will be launched using the TypeScript template as shown in the image below. On the left sidebar, we have a bunch of files.

Create React App

We have App.tsx, we also have index.tsx which is where the application entry point is. Likewise, we have some tests which are also written in TypeScript so that we can get TypeScript information inside our tests.

Our application uses a testing library called Testing Library with its React support, and we can know what is going on by reading the App.test.tsx file.

It is also worth noting that we get Intellisence support through the help of the testing library.

Intellisence support

We will concentrate on the functional part of the application only and not the testing part. The next step will involve invoking the terminal once again and running the below command as shown in the image below.

npm start

npm start

Note that we are getting the two addresses given to us in the terminal as shown in the above image i.e., the local server and the local network or rather IP addresses. We can use either to launch our App.

Our App is supposed to launch on the web browser automatically as shown in the image below.

It is important to note that your system’s anti-virus may stop the App from launching, this will be the case if it mistakenly detects the App as being a malware as is the case with me here!

When this happens, to get around it, you will have to enter either of the addresses in the browser address bar manually as displayed in the below two images.

React App screen
Create react app screen

Our React application is working.

It is ready to ship to production because it is as complex as the application needs to be at the moment. But let us not ship it to its current state, let us add some flavor to it by adding a count functionality.

Let’s go with the canonical example and build a counter component, we are going to do this as a function component and we will call it counter.

The counter is going to return a Div, and inside of the Div, we will have a P tag and the count is going to be a number.

For anybody who is not familiar with TypeScript, you will notice here that we are literally able to put that HTML right in our code with JavaScript. Peanut butter and chocolate coming together.

import React from 'react';
import logo from './logo.svg';
import './App.css';

function Counter() {
return (
  <div>
    <p>Count: {count}</p>
  </div>

);
}

function App() {
  return (
    <div className="App">
     <header className="App-header">
        <img src={logo} className="App-logo" alt="logo" />
        <p>
          Edit <code>src/App.tsx</code> and save to reload.
        </p>
       <a
          className="App-link"
          href="https://reactjs.org"
          target="_blank"
          rel="noopener"
        >
          Learn React
       </a>
      </header>
    </div>
  );
}

export default App;

For those of us that aren’t familiar with React, tsx, or jsx syntax allows us to build/use angle brackets within sight of our JavaScript, so we can put Tags and P tags around custom components and so on and so forth.

We put the tags in our code and when react runs, it will generate them to be valid method calls against the React API and as a result, make our UI appear.

Counter Component

We start by creating a Counter function and pass a count property as a parameter, but we get a little red warning!

This happens as a result of the compiler trying to ask “you said you wanted something called counter here, but you haven’t told me what that is, right?”

Since it is a prop that we want to pass on, it comes in as the first argument. We are going to deconstruct it as demonstrated in the code snippet below.

function Counter ({ count }) {
return (
  <div>
    <p> Count: {count}</p>
  </div> 

);
}

We have told the compiler where the count is coming from, but still, the compiler is asking – “Well, it might be coming from there, but I still don’t know what it is!”

If you have a keen look at the error message itself, it is saying that this was declared to be of any type.

Why Avoid “Any” Type

Using Any type is the same as telling the compiler, you have the liberty to choose which type you want to use for this particular object, function, variable, constant, etc.

The TypeScript compiler isn’t trained like this so it raises an alarm complaining that this type has not been clarified thus, it could be a number, it could be a string, it could be an object, it could be a function, it could be anything!

TypeScript compiler is asking us – “Maybe you want to help me out and give me some information about what this is actually going to be.”

“What is that argument looking like? What is the shape of it and what are the types of the properties available within it?”

The reason behind the TypeScript compiler triggering the alert is because we have this rule turned on that says that we are not allowed to have implicit any’s anywhere in our code.

This is something that’s turned on in our TypeScript config, and it is one of the rules that TypeScript sets by default in the compiler because you want to try and avoid using any in your application.

The main reason is the more any’s that you have, the less value TypeScript can give you, because you’re basically telling TypeScript compiler, ignore this, ignore that, ignore this also, ignore that too….

The more you do that, the more you start questioning what value TypeScript is going to be bringing on board? We will go ahead and define an object shape for the property. This will be called count, and that’s going to be a number.

In the code snippet below, what I have done is, I have put a colon which indicates that this is an object. This is exactly how we would do a type annotation of an object in TypeScript.

I am annotating it with a type that is just like an inline anonymous type. Indeed, that count is going to be a number.

function Counter ({ count }: {count: number}) {
return (
  <div>
    <p>Count: {count}</p>
<div>

);
}

If I hover over count, it knows that it is a number as shown on the image below. Excellent, the error disappears since we have told the compiler what the count is and its type. Let us proceed and add this component to our application.

component to our application

We can also create an interface out of that if we want and maybe share that out with someone else. If that is what we want to do.

extract to interface

You’ll see in the Vs code that we have this little light bulb that just pops over to your code.

When I highlight that anonymous type, and then I do CTRL+dot, which activates that code tip, it says, do you want to extract that as a type alias or as an interface?

Let’s opt for Interface and then name it counterProps.

import React from 'react';
import logo from './logo.svg';
import './App.css';

interface CounterProps {
  count: number;
}

function Counter ({ count }: CounterProps) {
return (
  <div>
    <p>Count: {count}</p>
  </div>

);
}

function App() {
  return (
    <div className="App">
      <header className="App-header">
        <img src={logo} className="App-logo" alt="logo" />
        <p>
          Edit <code>src/App.tsx</code> and save to reload.
        </p>
        <a
          className="App-link"
          href="https://reactjs.org"
          target="_blank"
          rel="noopener"
        >
          Learn React
        </a>
      </header>
    </div>
  );
}

export default App;

We can extract that out. if you are sharing these across multiple files, then maybe we can extract that out, and then you could have that interface as something you could use elsewhere.

function App() {
  return (
    <div className="App">
      <header className="App-header">
       <Counter/>
      </header>
    </div>
  );
}

Next, we should just delete out some of the unnecessary code we have inside our code and we are going to put our counter in that place instead. But before we proceed further, I hope you have realized that we have another red warning as shown in the image below.

Red warning

The red arrow is telling us that the property count is missing because we are not passing any props to that component.

Suppose we were creating a shared component design in React, this would be the most common way to build react components. But since this does not react, we need to pass the default value for the count.

I assumed that the count was always going to be managed by the counter itself. Well, you need to pass the value, so the count will be Hello as shown in the code snippet below.

function App() {
  return (
    <div className="App">
      <header className="App-header">
       <Counter counter= {"hello"}/>
      </header>
    </div>
  );
}
View Problem

Behold, we are getting an error message as shown in the image above, this is because the counter is not what we have named it. It will tell us that the property that we have given to the counter does not match with what is expected at the count.

function App() {
  return (
    <div className="App">
      <header className="App-header">
       <Counter count= {"hello"}/>
      </header>
    </div>
  );
}

We will now get an error compiler saying, “well, you’ve given a string, but I expect a number. Again, TypeScript is just making sure that we could have provided zero.” This error is coming from an API call that notices that this is a string.

That is why the TypeScript compiler is complaining that you’ve given me a string, but I needed a number. Finally, we will put a zero there as shown in the function code snippet below.

Save that.

import React from 'react';
import logo from './logo.svg';
import './App.css';

interface CounterProps {
  count: number;
}

function Counter({ count }: CounterProps) {
return (
  <div>
    <p>Count: {count}</p>
  </div>

);
}

function App() {
  return (
    <div className="App">
      <header className="App-header">
       <Counter count = {0}/>
      </header>
    </div>
  );
}

export default App;

Let us refresh your browser, you will notice that we now get our value as we expect as displayed in the image below.

Refresh

React Hooks

Let’s go ahead and have a look at how we can make that value change using React hooks and see what we can do with TypeScript and React hooks. We need to import the react hooks and we will put them in useState.

import React, { useState } from "react";

React hooks is a way of managing the state of a function component because the function component does not have a state of its own, but we can use the react hooks APIs to set that up.

We will create some states, then we will proceed to set the count and then use the state. Take a look over the type signature that is just popping up as shown on the image below.

React Hooks

We can say that useState can take a generic argument, let me expound more on that. useState can take a generic argument which is going to be S. This is the label that the compiler has decided to give in the type definition.

S is the initial state. This is where our function is destined to return to its initial state. The generic argument is going to be returned as the first value of the deconstructed array, and then we will have a function that will modify that.

If we leave our code as shown on the image above, we might think that count is OK, but that is not the case since it is undefined. It does not have a value associated with it.

To curb this issue, let us give it a generic argument of type number as shown in the code snippet below. Check the image that follows below and notice that now the intellisence shows us that our hook i.e. useState is of type number or undefined.

function App() {
  const [count, setCount] = useState<number>()
  return (
    <div className="App">
      <header className="App-header">
       <Counter count = {0}/>
      </header>
    </div>
  );
}
public option

Now we know that the count will either be a number, or it could be undefined because we have not given it a default value as shown on the image above.

Let us give it a default value of zero instead. Count is now never going to be a number because we’ve initialized it and we can go ahead and remove our generic argument as clearly shown below.

function App() {
  const [count, setCount] = useState(0)
  return (
    <div className="App">
      <header className="App-header">
       <Counter count = {0}/>
      </header>
    </div>
  );
}

The compiler knows that a count is a number because it is inferred from zero being a numerical value. So, the number is the type and setCount will be an updated function that takes a number to update the count value.

Now instead of passing zero to set count, we can pass in the count and our UI still respects what we are expecting it to return i.e. zero, and works the way we want it to work as shown on the image below.

setCount

Counter Buttons

Let us add a plus symbol button and then create another button to be a minus symbol. The two buttons will be used for increment and decrement. Then we will add an onClick listener to the buttons.

This time we will give it zero arguments because we can ignore that first argument. We don’t need the event argument that’s happened from that click. Instead, we are going to count and reset the count plus one.

Then we will just copy the first button line of code down to the second line of code, and instead of plus one, we will make it minus one as shown on the code snippet below.

Save that and refresh your browser and click the buttons to increment and decrement the counter respectively.

function App() {
  const [count, setCount] = useState(0)
  return (
    <div className="App">
      <header className="App-header">
        <button onClick = {() => setCount(count + 1)} >+</button>
       <Counter count = {count}/>
       <button onClick = {() => setCount(count - 1)} >-</button>
      </header>
    </div>
  );
}
Counter Buttons

Now our counter goes up and our counter goes down, and this is all done in a type-safe manner. We know that the counter requires a number passed to it. We know that count is going to be a number.

We have an external component that happens to have a few lines above i.e. the Counter, but it could be coming from another file. We have a prop that we expect, which is a number, and we are passing it on in a number as well.

Inside that, it is getting a number and it is outputting it. It is converting it to a string so it can output it inside that P tag.

If we were to change that and replace zero with number as it was initially as the generic argument. You will see a bunch of errors as shown in the image below.

This is because it could be a number that has not been defined since it was never initialized.

Counter default

We can’t pass it to our external component because it is a number or undefined, the main reason being we only want a number. This is where TypeScript makes things so much more powerful.

import React, { useState } from "react";
import logo from './logo.svg';
import './App.css';

interface CounterProps {
  count: number;
}

function Counter({ count }: CounterProps) {
return (
  <div>
    <p>Count: {count}</p>
  </div>

);
}

function App() {
  const [count, setCount] = useState(0)
  return (
    <div className="App">
      <header className="App-header">
        <button onClick = {() => setCount(count + 1)} >+</button>
       <Counter count = {count}/>
       <button onClick = {() => setCount(count - 1)} >-</button>
      </header>
    </div>
  );
}

export default App;

Count - 3

Conclusion

In this tutorial, we have learned how to go about Create-React-App with TypeScript. To begin with, we saw that we need to install the create-react-App by running the below command on the terminal.

npx create-react-app app –template typescript

The template React App has TypeScript generated tests that help us with important information, this is made possible through the help of the Test Library.

To launch the app, run the below command on the terminal

npm start

We use TypeScript because it is a safe type of language, so including any’s in our code will demeanor the power of TypeScript.

React hooks help us to install a state in our function component since it doesn’t have a state of its own. React hooks can take generic arguments.

TypeScript is much more powerful since it can’t pass a prop to an external component if the props type is unknown or undefined, isn’t that type security?

PREV Tutorial | NEXT Tutorial

Was this helpful?

Thanks for your feedback!

Leave a Comment