How to Use Typescript with React?
Last Updated on
Sep 5, 2024
Key Takeaways
- Writing TypeScript with React.js is a lot like writing JavaScript with React.js. The main advantage of using TypeScript is that you can provide types for your component’s props which can be used to check correctness and provide inline documentation in editors.
- TypeScript enables developers to use modern object-oriented programming features. TypeScript Generics allows the creation of flexible react components that can be used with different data structures.
- With TypeScript in React Project, one can perform more compile-time checks for errors and some features become easier to develop.
- For TypeScript with React, one can refer to community-driven CheatSheet – React TypeScript covering useful cases and explanations in depth for various modules.
Although TypeScript is a superset of JavaScript, it is a popular programming language in its own right. Developers tend to feel confident programming with TypeScript as it allows you to specify value types in the code. It has a large ecosystem consisting of several libraries and frameworks. Many of them use TypeScript by default but in the case of React, you are given the choice whether to use TypeScript or not.
React is a JS-based library that enables you to create UIs using a declarative, component-based method. Using TypeScript with React has proven to be very effective. You can observe that the offerings of a reputed software development company include React services that focus on crafting elegant user interfaces. In contrast, TypeScript is leveraged to identify code errors, improving the project’s overall quality.
This tutorial will guide you on how to use TypeScript with React. But first, let’s clear our basics.
1. What is Typescript?
Microsoft created a high-level programming language called TypeScript. It is statically typed. So, it automatically introduces static type checking to your codebase to improve its quality.
Although React projects mostly use JavaScript, certain features like type annotations, interfaces, and static types that are necessary to detect code errors early on are only available with TypeScript.
There are many perks such as improved collaboration in large-scale projects, increased productivity, and improved code quality for utilizing types from TypeScript. Because it offers the means to define the data format and structure, the language ensures type safety along with the prevention of runtime errors.
The conjunction of React and TypeScript enables the developers to build strongly typed React components. It also enforces the type checking in state and props which helps make your code more robust and reliable.
TypeScript offerings such as documentation and advanced code navigation features further simplify the work of developers. You can develop robust and easy-to-maintain React applications effortlessly by leveraging the React-TypeScript integration capabilities.
Further Reading on: JavaScript vs TypeScript
2. React: With JavaScript or TypeScript? Which one is Better?
JavaScript is a popular scripting language. More often it’s the first programming language developers learn for web development. React is a JS-based library that developers prefer to use for building UIs.
On the other hand, TypeScript is JavaScript’s superset. So, it offers all the benefits of JavaScript. On top of that, it also provides some powerful tooling and type safety features. Using these languages has its own merits and demerits. So, the choice of whether to use TypeScript or JavaScript with React in your project boils down to your requirements.
JavaScript features such as high speed, interoperability, rich interfaces, versatility, server load, extended functionality, and less overhead make it a perfect candidate for building fast-changing apps, browser-based apps and websites, and native mobile and desktop applications.
TypeScript features like rich IDE support, object-oriented programming, type safety, and cross-platform and cross-browser compatibility allow you to build complex and large-scale applications with robust features.
3. Why Do We Use Typescript with React?
To avail a multitude of advantages. Some of them are:
- Static Type Checking: Static Typing was introduced for React projects in TypeScript. It helps developers identify errors early on. This early detection of potential errors and prevention of runtime errors is possible because of the enforcement of type annotations from the programming language. It makes your code robust and reliable.
- Improved Code Quality: Typescript language allows the developers to define the return values, function parameters, and strict types for variables. This helps in writing a clean and self-documenting code. The Type system of the language encourages the developers to write more structured and high-quality code. So, your code becomes easy to read and maintain.
- Enhanced Developer Productivity: The code editors of TypeScript come with features like real-time error checking, type inference, and auto-completion as a part of advanced tooling support. This helps developers code quickly, find mistakes, implement better coding suggestions, minimize the debugging time, and in the end enhance productivity.
- Better Collaboration: It might pique your interest to know that apart from providing coding advantages, TypeScript offers collaboration advantages as well. It provides contract definitions and clear interfaces through type annotations and interfaces. It helps developers understand how different modules and components interact. This improves the overall project understanding.
4. Create a React Application with Typescript
Explore the steps mentioned below to create a React application with Typescript.
4.1 Prerequisites
Before we get into action, make sure you are prepared for it. What you will need includes:
- One Ubuntu 20.04 server. Make sure it is firewall enabled and comes with a non-root user and sudo privileges. Ubuntu 20.04 offers an initial server setup guide. It would help you get started.
- Install nodejs and NPM. Use a NodeSource PPA with an Apt. You have to install them on Ubuntu 20.04 to get started.
4.2 Create React App
Create-react-app v2.1 comes with a TypeScript by default. While setting up the new project with CRA, you can use TypeScript as the parameter.
npx create-react-app hello-tsx --typescript |
Tsconfig.json is generated when TypeScript is used for project setup.
4.3 Install TypeScript in the React App
To add a TypeScript version to an existing application, you have to install it with all the necessary types. Execute the following code:
npm install --save typescript @types/node @types/react @types/react-dom @types/jest |
Next, rename all your files with ts file and tsx file extension. After that, you can start your server which will automatically produce a JSON file named tsconfig.json. Once that happens, you can start writing React in TypeScript.
It is important to note that adding TypeScript to existing projects doesn’t mean it will affect the app’s JS code. It would work fine and if you want, you can migrate that code to TypeScript as well.
4.4 How to Declare Props?
The following example depicts how you can use TypeScript to type props in a React component.
import React from 'react'; type DisplayUserProps = { name: string, email: string }; const DisplayUser: React.FC<DisplayUserProps> = ({ name, email }) => { return ( <React.Fragment> <h1>{name}</h1> <h2>{email}</h2> </React.Fragment> ) } export default DisplayUser; |
A custom type for DisplayUserProps is defined in the code above. It also includes the name and email. The generic type of React Functional Component is used to define the DisplayUser by taking pre-defined DisplayUserProps as arguments.
So, wherever we use the DisplayUser component, we will get the data back as the props. It helps confirm the predefined types such as name and email. The component is called inside App.tsx.
const App = () => { const name: string = "Cherry Rin"; const email: string = "cherryrin@xyz.com"; return ( <DisplayUser name={name} email={email} /> ); }; export default App; |
After reloading the React app, when you check the UI, it renders the name and email as shown in the example below:
The TypeScript shows an error when you pass the data that isn’t part of the data structure.
<DisplayUser name={name} email={email} age={30} /> |
Your console will display the error message as follows:
It is how TypeScript ensures that defined types are adhered to when props are passed to the DisplayUser component. This also helps enforce error checking and type safety in the development process.
4.5 How to Declare Hooks?
useRef and useState are the two most common React hooks used in TypeScript.
Typing the UseState hook
Without Types, the useState will look similar to the following command:
const [number, setNumber] = useState<>(0) |
With Types, the useState will look like:
const [number, setNumber] = useState<number>(0) |
And just like that, you can simply declare the state value’s types. The value is determined in <number>. If you or anyone else tries updating the state with another value, the action will be prevented with an error message.
But if you want your state to hold different values then you have to declare:
const [number, setNumber] = useState<number | string>(0). |
After running this command, you can enter any string or number and it won’t count as an error.
The following example depicts how you can use useState in a React component,
import DisplayUsers from './components/DisplayUsers'; import { useState } from 'react'; const App = () => { const [name, setName] = useState<string>('Cherry Rin'); const [email, setEmail] = useState<string>('cherryrin@xyz.com'); return ( <DisplayUser name={name} email={email} /> ); }; export default App; |
Typing the UseRef hook
In React, a DOM component is referenced using the useRef hook. The example given below shows how you can implement it in TypeScript with React.
const App = () => { const nameRef = useRef<HTMLInputElement | null>(null); const saveName = () => { if (nameRef && nameRef.current) { console.log("Name: ", nameRef.current.value); } }; return ( <> <input ref={nameRef} type="text" name="name" id="name" /> <button onClick={saveName}>Save</button> </> ); }; |
Output:
We will be starting with the ref variable as null and declare HTMLInputElement | null as its type. While using the useRef hook with TypeScript, you can assign it to either null or to declared type.
The benefit of declaring the useRef hook is that you won’t be reading data or taking actions from the unmatched types as TypeScript will be there to prevent you. You will get the following errors in case for ref, you try to declare a type number.
It helps you avoid making silly errors which saves time that you would have been otherwise spending on debugging. While working on large projects, where multiple people are contributing to the codebase, using TypeScript for React apps provides you with a more ordered and controlled work environment.
4.6 How to Declare and Manage States?
If you have working experience with React or a basic understanding, you would know that adding a simple and stateless component to your React apps isn’t entirely possible. To hold state values in your app component, you have to define state variables.
The state variable is defined with a useState hook as shown below:
import React, { useState } from "react"; function App() { const [sampleState, setSampleState] = useState("Ifeoma Imoh"); return <div className="App">Hello World</div>; } export default App; |
JavaScript
In this case, the type of state is presumed automatically. By declaring the type your state accepts, you can increase its safety.
import React, { useState } from 'react'; function App() { const [sampleState, setSampleState] = useState("Ifeoma Imoh"); //sampleStateTwo is a string or number const [sampleStateTwo, setSampleStateTwo] = useState<string | number>(""); //sampleStateThree is an array of string const [sampleStateThree, setSampleStateThree] = useState<string[]>([""]); return ( <div className="App"> Hello World </div>) } export default App; |
4.7 React Functional Component
In TypeScript, a functional component or a stateless component is defined with the following commands:
type DisplayUserProps = { name: string, email: string }; const DisplayUsers: React.FC<DisplayUserProps> = ({ name, email }) => { return ( <React.Fragment> <h1>{name}</h1> <h2>{email}</h2> </React.Fragment> ) } export default Count; |
With React.FC, we will define the expected props object structure. Utilizing props is one of many ways to create the interface.
interface DisplayUserProps { name: string; email: string; }; const DisplayUsers: React.FC<DisplayUserProps> = ({ name, email }) => { return ( <React.Fragment> <h1>{name}</h1> <h2>{email}</h2> </React.Fragment> )} |
4.8 How to Display the Users on the UI?
Now, what shall we do to display the user’s name and email on the screen? The console consists of the name property for all objects. These objects have the user’s name and email. We can use them to display the user’s name and email.
Now, you have to replace the content in the App.tsx file with the following:
import React, { useState } from 'react'; import { UserList } from '../utils/UserList'; export type UserProps = { name: string, email: string }; const DisplayUsers = () => { const [users, setUsers] = useState<UserProps[]>(UserList); const renderUsers = () => ( users.map((user, index) => ( <React.Fragment> <div key={index} style={{ borderBottom: "1px solid black" }}> <p>{user.name}</p> <p>{user.email}</p> </div> </React.Fragment> )) ); return ( <React.Fragment> <h1>User List</h1> {renderUsers()} </React.Fragment> ) } export default DisplayUsers; |
The users array is looped over using the array map method. To destructure the name and email properties of each user object, the object destructuring method is used. Here, the user’s name and email will be displayed on the screen as an unordered list.
Now is the time to determine a user as an object that has properties like name and email. For every property, we also have to define a data type. Next, you have to change the useState users array from:
const [users, setUsers] = useState([]); |
to :
const [users, setUsers] = useState<UserProps[]>(UserList); |
It is to specify users as an array of type users’ objects. It is our declared UI. So, if you check your App.tsx files now, you will see that it no longer has any TypeScript errors.
As a result, you can see that the screen is displaying a list of 5 random users.
4.9 Run App
Until now, we discussed the basic yet most important concepts for React app development using TypeScript. This section will show how you can leverage them to create a simple to-do app.
Create a new React-TypeScript project like we did at the beginning of the article. After that, you have to run the code given below at the app’s root level to start the development server.
npm start Shell |
Now, open the App.tsx file. It consists of a code which you have to replace with the following:
import DisplayUser, { DisplayUserProp as UserProps } from './components/DisplayUser'; import React, { useEffect, useState } from 'react'; import { UserList } from './utils/UserList'; const App = () => { const [users, setUsers] = useState<UserProps[] | []>([]); useEffect(() => { if (users.length == 0 && UserList) setUsers(UserList); }, []) const renderUsers = () => ( users.map((user, index) => ( <React.Fragment key={index}> <DisplayUser name={user.name} email={user.email} /> </React.Fragment> )) ); return ( <React.Fragment> <h1>User List</h1> {renderUsers()} </React.Fragment> ); }; export default App; |
Here, User data comes from the UserList.ts file which is inside the utils folder. Add the below-mentioned data to the UserList.ts file:
import { DisplayUserProp as UserProps } from "../components/DisplayUser"; export const UserList: UserProps[] = [ { name: "Cherry Rin", email: "cherryrin@xyz.com" }, { name: "Lein Juan", email: "leinnj23@xyz.com" }, { name: "Rick Gray", email: "rpgray@xyz.com" }, { name: "Jimm Maroon", email: "jimaroonjm@xyz.com" }, { name: "Shailey Smith", email: "ssmith34@xyz.com" }, ]; |
To render individual User items in your app, you have to import a DisplayUser component. We will be creating it next. But first, go to your app’s src directory. Open a new components folder. In there, create a DisplayUser file with the tsx extension. Now add the following code to it.
import React from 'react'; export type DisplayUserProp = { name: string, email: string }; const DisplayUser: React.FC<DisplayUserProp> = ({ name, email }) => { return ( <div style={{ borderBottom: "1px solid black" }}> <p>{name}</p> <p>{email}</p> </div> ) }; export default DisplayUser; |
After saving all the modifications, test your React app in the browser.
5. Conclusion
In this article, we have surfed through the fundamentals of using TypeScript with React development. These are the concepts that are widely used in your typical TypeScrip-React projects. We also saw how you can integrate these concepts to build a simple React application. You can imply them similarly in other projects with little modifications to suit your requirements.
If you have any queries or input on the matter, feel free to share them with us in the comments section below. We will get back to you ASAP!
FAQs
Can You Use TypeScript with React?
When it comes to adding type definitions in a JS code, developers prefer to use TypeScript. Only by adding @types/react and @types/react-dom to your React Project, you can get complete JSX and React web support.
Is TypeScript better for React?
With static typing, TypeScript helps the React compiler detect code errors early in the development stage. On the other hand, because JavaScript is dynamically typed, the compiler has a hard time detecting code errors.
View Comments
This blog post is a great introduction to TypeScript for React devs! It covers the benefits (like catching errors early) and guides you through building a simple app with TypeScript. Especially helpful is the breakdown of using types for props and state management.