How to Use TypeScript with React

Using TypeScript with React can significantly enhance your development experience by providing type safety, better tooling, and improved code readability. TypeScript helps catch errors during development instead of runtime, which is especially helpful in large applications. Here’s a step-by-step guide on how to get started using TypeScript with React.

  1. Setting Up a React Project with TypeScript

Option 1: Create a New Project with Create React App

The easiest way to set up a new React project with TypeScript is to use Create React App (CRA) with the TypeScript template.

“`bash

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

cd my-app

“`

This command creates a new React app named `my-app` with TypeScript already configured.

Option 2: Add TypeScript to an Existing React Project

If you already have a React project and want to add TypeScript, follow these steps:

  1. Install TypeScript and the necessary type definitions:

“`bash

npm install –save typescript @types/react @types/react-dom

“`

  1. Create a `tsconfig.json` file in the root of your project:

“`json

{

“compilerOptions”: {

“target”: “es5”,

“lib”: [“dom”, “dom.iterable”, “esnext”],

“allowJs”: true,

“skipLibCheck”: true,

“strict”: true,

“forceConsistentCasingInFileNames”: true,

“noEmit”: true,

“esModuleInterop”: true,

“module”: “esnext”,

“moduleResolution”: “node”,

“resolveJsonModule”: true,

“isolatedModules”: true,

“jsx”: “react-jsx”

},

“include”: [“src”]

}

“`

  1. Rename your `.js` files to `.tsx` (for React components) or `.ts` (for regular TypeScript files).
  2. Basic TypeScript Concepts

Type Definitions

You can use TypeScript’s type system to define variable types, function return types, and props for React components. Some common types include:

– String: `let name: string;`

– Number: `let age: number;`

– Boolean: `let isLearned: boolean;`

– Array: `let numbers: number[];` or `let names: Array<string>;`

– Object: You can define an interface or type for objects.

Interfaces and Types for Props

When creating React components, you can define the types for props using interfaces or type aliases.

“`tsx

interface GreetingProps {

name: string;

}

const Greeting: React.FC<GreetingProps> = ({ name }) => {

return <h1>Hello, {name}!</h1>;

};

“`

  1. Creating a Simple React Component in TypeScript

Here’s a simple example of a React component with TypeScript:

“`tsx

import React from ‘react’;

interface Todo {

id: number;

task: string;

completed: boolean;

}

interface TodoListProps {

todos: Todo[];

toggleTodo: (id: number) => void;

}

const TodoList: React.FC<TodoListProps> = ({ todos, toggleTodo }) => {

return (

<ul>

{todos.map(todo => (

<li key={todo.id} onClick={() => toggleTodo(todo.id)}>

<span style={{ textDecoration: todo.completed ? ‘line-through’ : ‘none’ }}>

{todo.task}

</span>

</li>

))}

</ul>

);

};

export default TodoList;

“`

  1. Using TypeScript with Functional Components and Hooks

When using React hooks with TypeScript, you can specify the types of state variables and function callbacks.

“`tsx

import React, { useState } from ‘react’;

const Counter: React.FC = () => {

const [count, setCount] = useState<number>(0);

const increment = () => {

setCount(prevCount => prevCount + 1);

};

return (

<div>

<p>Count: {count}</p>

<button onClick={increment}>Increment</button>

</div>

);

};

export default Counter;

“`

  1. TypeScript with Context API

When using the Context API, you can define types for the context value.

“`tsx

import React, { createContext, useContext, useState } from ‘react’;

interface AuthContextType {

user: string | null;

login: (user: string) => void;

logout: () => void;

}

const AuthContext = createContext<AuthContextType | undefined>(undefined);

const AuthProvider: React.FC<{ children: React.ReactNode }> = ({ children }) => {

const [user, setUser] = useState<string | null>(null);

const login = (username: string) => {

setUser(username);

};

const logout = () => {

setUser(null);

};

return (

<AuthContext.Provider value={{ user, login, logout }}>

{children}

</AuthContext.Provider>

);

};

const useAuth = (): AuthContextType => {

const context = useContext(AuthContext);

if (context === undefined) {

throw new Error(‘useAuth must be used within an AuthProvider’);

}

return context;

};

export { AuthProvider, useAuth };

“`

  1. Error Handling and Type Inference

TypeScript can infer types in various situations, but always strive to explicitly define types when creating functions, especially when the structure of the data is essential:

“`tsx

const handleError = (error: Error): void => {

console.error(error.message);

};

“`

  1. Using Type Definitions for External Libraries

When using third-party libraries, install the necessary type definitions if available. For example, for libraries like Axios, you can do:

“`bash

npm install axios

npm install –save-dev @types/axios

“`

  1. Testing

TypeScript works well with testing libraries like Jest and React Testing Library. You can define types for your test cases similarly to how you would in your components.

Conclusion

Using TypeScript with React provides a robust way to develop applications, bringing type safety and better tooling support. By defining types for props, state, and context, you can catch potential errors early in the development process. Start building your application with these practices in mind, and you’ll appreciate the benefits TypeScript brings to your React projects!