TypeScript Logo

What to Read When Using React Typescript In Your App

October 1, 2022
Temitope Asama
React.js

The Fastest Way to Build React UI

Convert Figma designs to production-ready React.js code. Build stunning apps and landing pages faster than your peers and competitors.

Introduction

These days, businesses are migrating their applications and digital product from plain ol’ Javascript to Typescript.

Why? Well, we could liken Typescript to Javascript with superpowers.

How? We’ll find out as we progress.

Before we go into details, check out this cool tool for converting Figma files to React code with Typescript support!

In this article, we’ll explain Typescript and its advantages over plain Javascript, as well as a guide to using Typescript in your React applications.

A Brief Introduction to React

React, maintained by Facebook and first made open-source in 2013, has grown to be one of the most widely used frameworks for front-end development. With the help of frameworks like Redux, React can be quickly expanded to add features like routing, caching and state management methods.

It is a declarative and adaptable JavaScript UI library that drives componentization and reusability. It enables you to build intricate user interfaces out of discrete, little chunks of code known as “components.”

To learn more about this library, check out the official React documentation or this React Crash Course on YouTube.

At CopyCat, we also have a robust stash of wonderful, beginner-friendly React articles, check them out here!

Typescript: A superset of Javascript

TypeScript is a free, open-source programming language built and maintained by Microsoft. It is a strict superset of JavaScript and extends it with class-based, object-oriented programming and optional static typing. It may be used to build on the client-side (web browser) and server-side applications (Node.js or Deno).

Simply put, Typescript is Javascript with the ability to add static type checking at any time. Static type checks in Javascript are a fantastic concept and a major reason why Typescript adoption is fast growing. This is because Typescript functions like a built-in unit test and provides us with the advantage of the compiler watching our back, prompting errors long before the code is run, saving us countless bugs in our applications and enforcing best practices by giving static and robust typing to our apps.

As cool as it is, browsers lack the ability to run Typescript, and for this reason, Typescript is first compiled, at build time, to Javascript, which browsers can process at runtime.

Understanding Types in TypeScript

Types are Typescript’s main mechanism of adding static type capabilities to Javascript applications and they can be implied either implicitly or explicitly.

A type, simply put, describes the different properties and functions that a value has i.e. it tells us what should be a string, or a number, or even an array.

Take the variable below, for example;

const myVar;

Say, somewhere later in our code, we want to assign a number to myVar. Using plain old Javascript, we might forget this somewhere along the line and assign a string to it, and in cases where we might need to use myVar in some computational logic, this can cause errors in our code that we may only find out at runtime.

Typescript, however, can help us prevent this using types. These types ensure that the right data type for a particular variable is what we assign to it; and in cases where we make mistakes like the aforementioned, it immediately throws an error to let us know something is wrong. Now, this is the basic idea of using Typescript with React or any other framework when building applications.

Types in Typescript

There are several types in Typescript for several different purposes. However, the basic, everyday types in Typescript include;

  • String
  • Number
  • Boolean
  • Array
  • Object
  • Tuple
  • Enums
  • Null and Undefined

We can add types to our example above as thus;

let myVar: number;

What we have done above is simply tell typescript that we want the value of myVar to be a number. Such that if we mistakenly assign a string, boolean, an array or any other type to it, it throws an error.

For example, if we assign a string to myVar;

myVar = "I use Copycat to convert my Figma files to React code"

We get an error right in our console or IDE that says;

Argument of type ‘number’ is not assignable to parameter of type ‘string’

and like that, before we even run our code, we are made aware of our error.

To go in-depth into Typescript and its functionalities, check out the full Typescript documentation and this Youtube tutorial by Academind.

PropTypes

If you’ve been writing React for a while now, you’ve probably heard of PropTypes. What are PropTypes and how do they differ in function from Typescript?

What is PropTypes?

PropTypes is a runtime type-checking tool for props in React apps. It became available in React 15.5 as the prop-types package. Just like Typescript, with PropTypes, you can define the types of props you’re expecting in a component; you also have the option of stating whether the expected props are required or optional and when you pass a different type to a component or skip a required prop, you get a warning in the JavaScript console.

Difference between PropTypes and Typescript

So you may be wondering, how is it different? Why do I have to learn Typescript when I can just use PropTypes? Well, if you go back to the definition of PropTypes, you’ll see the highlighted word, “runtime”, and that is important because it is a key difference between Typescript and PropTypes.

With Proptypes, you can only see your error in your console after running your code, unlike with Typescript, where your error shows up right in your IDE!

In addition to that, PropTypes does not provide warnings in production applications; warnings are only evident during development. What this means is that if something breaks in production because of a wrong type, PropTypes provides no warnings.

To learn more on PropTypes in React and how to use the library, with robust examples, check out this article.

Why not Javascript: TypeScript vs Javascript

Using Typescript instead of its more popular cousin, Javascript, it is feasible to eliminate some software abnormalities or bugs sooner during development and ensure that the code is error-free before it is put into production.

Popularity survey of programming languages. Source: StackOverflow
Popularity survey of programming languages. Source: StackOverflow

Additionally, Typescript facilitates type management and special edge cases, which the development team would not have easily considered with plain vanilla Javascript. The team is compelled to consider these issues or approaches, and as a result, best practices are promoted, cutting down on development time and the likelihood of defects.

For a team that is more concerned with security, it is worthwhile to learn Typescript. Codes are checked for potential problems by types at compile time, preventing them from developing into vulnerabilities or errors and making it simpler to identify program flaws or errors early enough.

Credit: Cynoteck
Credit: Cynoteck

Advantages of using Typescript with React

React developers can benefit from TypeScript in a variety of ways. Just a few advantages of utilizing TypeScript in React are listed below:

Bug and variable checks

By examining the data type provided to statically declared variables, TypeScript provides variable checks. Overall, this lessens the likelihood of giving our variables the incorrect types.

Additionally, TypeScript performs compilation-time tests to help detect issues like incorrect parameter assignments, syntax errors, and much more. This is beneficial since it lessens the possibility of mistakenly calling the incorrect function or skipping a variable declaration.

Clean and readable code

The fact that TypeScript is a statically-typed script is its primary feature. The distinction between statically and dynamically typed programming languages is how type checking is carried out. Variables in static languages are type-checked.

Interfaces

You can create interfaces in TypeScript to define complex type definitions. This is particularly useful if you wish to use a complex type in your application, such as an object with multiple properties. Due to the tight checks that result, you are less likely to create defects than you could be.

Better JSX support

JavaScript XML is referred to as JSX. It enables us to directly write HTML code in our React project. Better IntelliSense and code completion for JSX are provided by using TypeScript with React.

Support for existing React projects

You may gradually migrate your application or existing projects from Javascript to Typescript. For this use case, the TypeScript compiler can also be configured to the project requirements or your preferences. The official TypeScript documentation contains a list of TypeScript compilers to this effect.

IDE support

When utilizing IDEs like Visual Studio, Visual Studio Code, Atom, Webstorm, Eclipse, and many more, TypeScript is also highly beneficial. Development is sped up by these superior autocomplete and snippet creation features.

How does TypeScript compile React code?

The tsconfig.json file

The magic of Typescript takes place in the tsconfig.json file. Typescript searches the project’s root folder for the tsconfig.json file, which contains compiler configuration settings.

To type-check our React code, Typescript builds it. Transpilation is required since Typescript is not understood by the v8-engine, which runs Javascript in the browser.

The Typescript compiler transforms Typescript into normal Javascript so that it may be used in our program using the tsc command. All .ts files in our project’s src directory are converted into .js files by the compiler as it traverses the path. It ignores files that aren’t in the src directory by default, however, the tsconfig.json file allows you to change this default setup to type-check tests and so on.

Getting Started with TypeScript: Installation and Configuration

There are two ways to create a react-typescript project.

You can either choose to install Typescript globally on your local machine and use it in your React project, or you can install Typescript locally to your React project alone using a template.

  1. Installing Typescript globally

Having TypeScript accessible across all projects might be useful, especially when testing out unique concepts.

So to that, all you need to do is run the following command on the CLI;

npm install -g typescript

The above command makes Typescript available on your local machine, ready to be used in any project.

After installing Typescript, we need to be able to run its compiler to compile our Typescript to Javascript. We can do this by running the tsc command anywhere in our CLI or even specific to our set-up project.

Just like that, we are able to install Typescript globally on our local machine for use in any project.

In the long run, however, the Typescript documentation suggests that;

“codebases should choose a project-specific installation over a global install so they can take advantage of replicable builds on various machines.”

With this in mind, let’s see how to install Typescript specifically for our React project.

  1. Installing a React project with a Typescript template

Setting up Typescript, per-project basis, allows you to have multiple projects running different versions of Typescript independently, allowing for project consistency and easy management.

We can create a new React project with a Typescript template like so;

npx create-react-app typescript-app --template typescript

or,

yarn create react-app typescript-app --template typescript

Once you run either of the above commands, your new application is successfully established without the need for any additional packages or special settings to be enabled. All of the files that would have been .js files are now .ts or .tsx files. like so;

React-typescript file structure
React-typescript file structure

Starting and Running the Development Server

To see your react-typescript project in action, run npm start to start your local development server.

Now that we know how to create a react-typescript project from scratch, what about when we have an already existing React project?

For an existing React project

To add TypeScript to an existing React project, navigate to your app directory, where you’ll want to install TypeScript and run the following command:

npm install --save typescript @types/node @types/react @types/react-dom @types/jest

or,

yarn add typescript @types/node @types/react @types/react-dom @types/jest

Installing React Dependencies

Above, we installed three different dependencies to allow us run Typescript in an existing React project. The following are the purpose of each package:

  • typescript – converts typescript files, which end in .ts or .tsx, into JavaScript.
  • @types/node – provides type definitions for Node.js.
  • @types/react – provides typing for the React API. Also offers IntelliSense and documentation.
  • @types/react-dom – provides typing for the React DOM API. Also offers IntelliSense and documentation
  • @types/jest – provides type definitions for Jest.

All dependencies provide typing throughout our entire React project.

Renaming Files

After installing the necessary packages, next up would be renaming .js files to .tsx. Any file you want to be TypeScript files should now have a .tsx suffix. For instance, App.js would now become App.tsx.

This is where problems could arise. You can see that practically everything is underlined in red when you open your App.tsx file. Not good.

Firstly, if you haven’t already, you should import React from the file’s top-level variable, “react.”

import React from "react"

Any underlined element in VSCode will display the warning “Cannot utilize JSX unless the ‘— jsx’ flag is specified” when you hover over it. At this point, you have the choice of manually fixing it or selecting the “Quick Fix” option. You will then get an option that says, “Enable the “— jsx” flag in your configuration file”. As soon as you click it, it takes a moment or two to load, after which the errors ought to disappear.

If you prefer to do it manually, open your tsconfig.json file, find the key “jsx,” and replace “react-jsx” with “react.”

{
  "compilerOptions": {
    "outDir": "./dist/",
    "noImplicitAny": true,
    "module": "es6",
    "target": "es5",
    "jsx": "react", // instead of "react-jsx"
    "allowJs": true,
    "moduleResolution": "Node"
  }
}

Your code ought to now be error-free and compile without any issues.

Typescript File Types: .ts vs .tsx files

Several updates after TypeScript v1.0, the.tsx extension was added to TypeScript. The.tsx extension was introduced in TypeScript v1.6, and it was intended to achieve two things, per the release notes:

  • Enable JSX in Typescript files
  • Make using the new “as” operator the standard casting method.

Three further outcomes of the .tsx introduction include:

  • Different plugins for .tsx files can be run by JavaScript bundlers like webpack, ESBuild, and others.
  • The ability for testing libraries like Jest to run .tsx files in a different test environment.
  • IDE support

Many developers were curious as to how the new file extension differed from the pre-existing.ts.

The distinction is actually quite simple to understand.

When constructing functions, classes, reducers, etc., that do not need to use JSX syntax or elements, you use the .ts file extension; but, when creating a React component and using JSX elements and syntax, you use the .tsx file extension.

Using Typescript with React Functional Components

A React Functional Component is a function that accepts props as parameters and returns JSX elements. In contrast to regular Javascript, where typing is accomplished by assigning types to variables and constants, React components attach types to props and state, therefore we must take into account the type of props being provided to our component.

To explain this, we will write all code in the App.tsx file to make things easier to understand. So, remove everything from the function in that file, then return the following code snippet;

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

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

Now that we have a cleaner file to work with, let’s go into details on how to create functional React components with Typescript.

Props Type as Argument

One of the simplest ways to declare a functional component is by declaring prop types as the function argument using an interface.

An interface describes the shape of an object in TypeScript. They can be used to tell the TypeScript compiler about the names of object properties and the datatypes that can be stored in their values. Strong type checking is a feature that an interface adds to your functions, variables, or the class that implements the interface.

The interface object specifies the type and name of the props. The interface keyword is used to declare the type first like so;

interface UserProps {
  id: number;
  firstName: string;
  lastName: string;
  getFullName(): string;
}

After that, we can annotate the function props to the interface object in our newly created User component like so;

// "User" component 
function User({ user }: UserProps) {
  return (
    <>
      <h1>Welcome {user.firstName}</h1>
    </>
  );
}

So our entire code should look like this;

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

//type declaration
interface UserProps {
  id: number;
  firstName: string;
  lastName: string;
  getFullName(): string;
}

function App() {
  return (
    <>
      <User name="Jane" />
    </>
  );
}

// "User" component 
function User({ user }: UserProps) {
  return (
    <>
      <h1>Welcome {user.firstName}</h1>
    </>
  );
}

export default App;

Inline Declaration of Types

Inline type declarations in the function component are another Typescript technique for building functional React components.   This method sidesteps specifying the props type and encourages adding them inline to the component itself.

So we can re-write our User component above as thus;

// "User" component 
function User({ user }: {
  id: number;
  firstName: string;
  lastName: string;
  getFullName(): string;
}) {
  return (
    <>
      <h1>Welcome {user.firstName}</h1>
    </>
  );
}

This method is rarely recommended as things become complicated as the component grows in complexity.

Using React.FunctionComponent

Importing React’s FunctionComponent type, also known as FC (which is merely an alias for FunctionComponent), is another typical approach to creating a functional component in React using Typescript. Usually, a function expression is used with this approach since we cannot create the component using a function declaration.

So using the UserProps interface declared earlier, we can re-write the User component like so;

const User: React.FC<UserProps> = ({ user }) => {
  return (
    <>
      <h1>{user.firstName}</h1>
    </>
  );
};

Disadvantages of the React.FC approach

Utilizing the React.FunctionComponent approach has the following drawbacks:

  • It implies the type of children: Even when we don’t want it, React.FC gives us access to a prop’s children. Even though we are not using the children’s prop, our app is forced to accept it.
  • It types a function instead of its parameters: We need to annotate the function type itself while using React.FC types. This means that when using React.FC, as in the example above, we must use a function expression, such as an anonymous function assigned to a const/variable or an arrow function.
  • Generics and React.FC are incompatible.

For those learning Typescript for the first time in React, React.FC can be useful because it provides type-based instructions. However, due to the drawbacks listed above, React.FC is usually not recommended for use.

Types for State and Props in React

It is also very possible to type-check state values in functional React components.

To specify a type for React.useState() or to inform TypeScript that a particular type is being assigned to a state property variable, useState() requires a <type> interface to be added after the word, useState, and before the opening parenthesis.

Consider the example below;

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

//type declaration
interface UserProps {
  id: number;
  firstName: string;
  lastName: string;
  getFullName(): string;
}

interface UserState {
  active: boolean;
  age: number;
}

function App() {
  return (
    <>
      <User name="Jane" />
    </>
  );
}

// "User" component 
function User({ user }: UserProps) {
  let [state, setState] = useState<UserState>({
    active: true,
    age: 17,
  });
  return (
    <>
      <h1>Hi!, I'm {user.firstName} and I'm {state.age} years old</h1>
    </>
  );
}

export default App;

Event and Form Handling with Typescript

How may the type supplied to an event on change or input be determined or specified? We can specify the kind of each event using one of the numerous built-in event types that React offers. Hovering over the event handler is one simple way to figure out the kind of event type to use for a specific event (e.g., onChange, onFocus, onSubmit).

Getting types for events. Credit: Open Replay
Getting types for events. Credit: Open Replay

Let’s demonstrate this with a simple form with event types in React;

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

//type declaration
interface UserProps {
  id: number;
  firstName: string;
  lastName: string;
  getFullName(): string;
}

interface UserState {
  active: boolean;
  age: number;
}

interface UserProfile = {
  username: string;
  password: string;
};

function App() {
 const [userProfile, setUserProfile] = useState<UserProfile>({
    username: "",
    password: "",
  });

  //Type-checking 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 (
    <>
      <User name="Jane" />
    </>
  );
}

// "User" component 
function User({ user }: UserProps) {
  let [state, setState] = useState<UserState>({
    active: true,
    age: 17,
  });
  return (
    <>
      <h1>Hi!, I'm {user.firstName} and I'm {state.age} years old</h1>
	<form onSubmit={login}>
        <div>
          <input
            name="username"
            value={userProfile.username}
            onChange={updateInput}
            type="text"
            placeholder="Username"
          />
        </div>
        <div>
          <input
            name="password"
            value={userProfile.password}
            onChange={updateInput}
            type="password"
            placeholder="Password"
          />
        </div>
        <input type="submit" />
      </form>
    </>
  );
}

export default App;

Learn more about typing events in React with this tutorial – https://www.youtube.com/watch?v=3PtiSy8G-Cs

Typing JSON Documents

Think of a situation where we need to type-check the data of a complex JSON object while retrieving it from an API. This can be challenging and most programmers would want to avoid it if at all feasible.

Using types for JSON data (API response), however, can be done quickly and securely by converting it to Typescript interfaces using programs like quicktype, transform, etc.

You can use the tools mentioned above to automatically generate the interface by simply copying and pasting the API JSON object into the tool.

Type-checking JSON objects with quick type
Type-checking JSON objects with quick type

Another example;

Quicktype converts our JSON object to typescript interfaces.
Quicktype converts our JSON object to typescript interfaces.

Promises with React Typescript

The Javascript promise is another Javascript feature that was added to Typescript. The data type of the value returned by the promise when it is resolved is determined by the return type of the promise, which is declared in Typescript immediately after the promise keyword.

Since errors can take on any form, Typescript sets the default data type of the result returned when the promise is rejected to “any.

Let’s examine the following React promise implementation example;

const typedPromise = new Promise<string>((resolve, reject) => {
      if (condition) {
        resolve();
        return;
      } else {
        reject(isEvenNumber);
      }
    });

    typedPromise
      .then((res) => console.log(res))
      .catch((err) => console.log(err));

We can conclude from the example above that, by default, our promise is expected to return a string.

Since this promise’s resolved data type is a string, tsc won’t permit us to call the resolve method with any other value than a string type.

We can implement similarly when we’re expecting a number or even an array.

Conclusion

Now that you know how to take React applications one notch higher with Typescript, I hope you found this article useful for either creating or migrating to Typescript with React.

To learn more about Typescript, check out the Typescript official documentation here. At Copycat, we have a robust stash of front-end articles and resources. Check it out here!

Copycat is a fantastic tool for building UI components faster with support for tools like Typescript, TailwindCSS, Bootstrap and more! It is your all-in-one plugin for converting your Figma files to up-and-running React code, saving up to 35% of development time! Get started today!

Related Articles

  • React.js

    Complete Guide to Bootstrap Tabs in ReactJS

    Introduction Bootstrap tabs are a popular component of the popular open-source front-end development toolkit, Bootstrap. It provides a way to create navigation elements on a web page quickly. This article will discuss how to use Bootstrap tabs to create navigation…

    December 20, 2022
  • React.js

    Complete Guide to Using Material UI Button in React

    Introduction Are you looking to add buttons to your React app? Material UI buttons provide an easy library for creating and customizing buttons with minimal coding. In this article, you'll learn how to install and use the material UI button…

    October 31, 2022

Convert Figma To React

Convert Figma designs to production-ready React.js code. Build stunning apps and landing pages faster than your peers and competitors.

Convert Design to Code