NashTech Blog

Using TypeScript in React: Tips for a Type-Safe Application

Table of Contents
react

By adding type safety, lowering runtime errors, and enhancing code readability, TypeScript integration with React can revolutionize your development experience. The static typing features of TypeScript facilitate team collaboration and the management of complicated applications. In this tutorial, we’ll cover the fundamentals of using TypeScript to make a more type-safe React application.

Why TypeScript with React?

React apps benefit greatly from TypeScript’s many advantages, which include:

  1. Type Safety: Avoid bugs by catching type-related errors during development.
  2. Enhanced Developer Experience: Take advantage of autocomplete and IntelliSense in modern editors.
  3. Easier Refactoring: With static typing, you’re more confident when modifying code as TypeScript highlights mismatches.

Setting Up TypeScript in a React Project

For a new React project with TypeScript, you can use:

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

Or, if you have an existing React project, install TypeScript and relevant type definitions:

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

You’ll also need a tsconfig.json file, which can be generated with:

npx tsc --init

Essential TypeScript Tips for a Type-Safe React App

1. Typing Props in Functional Components

TypeScript may guarantee that components receive the expected data by enforcing the shape of data supplied to them when types for props are defined.

type ButtonProps = {
  label: string;
  onClick: () => void;
};

const Button: React.FC<ButtonProps> = ({ label, onClick }) => (
  <button onClick={onClick}>{label}</button>
);

Here:

  • ButtonProps defines label as a string and onClick as a function.
  • Applying ButtonProps to the Button component with React.FC<ButtonProps> ensures the props match the defined structure.

2. Using the useState Hook with Explicit Types

The initial value can be used by the useState hook to infer types. Nonetheless, it is preferable to explicitly describe the type for more complicated types or undefined beginning values.

const Counter: React.FC = () => {
  const [count, setCount] = React.useState<number>(0);

  const increment = () => setCount(count + 1);

  return (
    <div>
      <p>Count: {count}</p>
      <button onClick={increment}>Increment</button>
    </div>
  );
};

Here, useState<number>(0) ensures count is always a number.

3. Typing useEffect Dependencies

You must make sure that values are typed appropriately, but TypeScript can help guarantee that dependency arrays in useEffect are accurate.

type User = {
  id: number;
  name: string;
};

const UserProfile: React.FC<{ userId: number }> = ({ userId }) => {
  const [user, setUser] = React.useState<User | null>(null);

  React.useEffect(() => {
    async function fetchUser() {
      const response = await fetch(`/api/users/${userId}`);
      const data = await response.json();
      setUser(data);
    }
    fetchUser();
  }, [userId]); // Ensure dependencies are typed accurately

  return <div>{user ? user.name : 'Loading...'}</div>;
};

4. Typing Event Handlers

React events have specific types in TypeScript, like React.ChangeEvent for form elements and React.MouseEvent for clicks.

const handleInputChange = (event: React.ChangeEvent<HTMLInputElement>) => {
  console.log(event.target.value);
};

const handleClick = (event: React.MouseEvent<HTMLButtonElement>) => {
  event.preventDefault();
};

5. Typing Custom Hooks

The type definitions provided by TypeScript can also be useful for custom hooks. In your hooks, define types for parameters and return values.

function useToggle(initialValue: boolean): [boolean, () => void] {
  const [value, setValue] = React.useState<boolean>(initialValue);

  const toggle = () => setValue((prev) => !prev);

  return [value, toggle];
}

const Component: React.FC = () => {
  const [isOn, toggleIsOn] = useToggle(false);

  return (
    <div>
      <p>{isOn ? 'On' : 'Off'}</p>
      <button onClick={toggleIsOn}>Toggle</button>
    </div>
  );
};

6. Typing Contexts

Define types for the Provider component and the context when utilizing TypeScript with React’s Context API.

type AuthContextType = {
  isAuthenticated: boolean;
  login: () => void;
  logout: () => void;
};

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

export const AuthProvider: React.FC = ({ children }) => {
  const [isAuthenticated, setIsAuthenticated] = React.useState(false);

  const login = () => setIsAuthenticated(true);
  const logout = () => setIsAuthenticated(false);

  return (
    <AuthContext.Provider value={{ isAuthenticated, login, logout }}>
      {children}
    </AuthContext.Provider>
  );
};

export const useAuth = () => {
  const context = React.useContext(AuthContext);
  if (!context) throw new Error('useAuth must be used within an AuthProvider');
  return context;
};

7. Using Type Assertions and Generics with useRef

Type assertions or generics can help the useRef hook, particularly when working with DOM elements.

const inputRef = React.useRef<HTMLInputElement>(null);

const focusInput = () => {
  if (inputRef.current) {
    inputRef.current.focus();
  }
};

return <input ref={inputRef} />;

8. Typing Default Props and Optional Props

Props can be made optional with TypeScript by adding? You can use TypeScript’s default value syntax or define your properties’ default values inline.

type GreetingProps = {
  name?: string;
};

const Greeting: React.FC<GreetingProps> = ({ name = "Guest" }) => (
  <p>Hello, {name}!</p>
);

Conclusion

By implementing type safety and minimizing runtime errors, TypeScript’s integration with React improves the dependability and maintainability of application development. TypeScript, which lets you create strict types for props, states, hooks, and other components, can be a useful tool for managing the codebase as React projects get more complex.

These pointers will help you create more type-safe React apps, cut down on mistakes, and enhance the development process. Adopt TypeScript to increase the scalability and resilience of your React code. Have fun coding! 🎉

Finally, for more such updates and to read more about such topics, please follow our LinkedIn page Frontend Competency.

Picture of kaushikichopra

kaushikichopra

Leave a Comment

Your email address will not be published. Required fields are marked *

Suggested Article

Scroll to Top