TypeScript

TypeScript for React Developers

Published on January 28, 2026

Written by: Code Arc Studio Editorial Team

TypeScript code on a screen

TypeScript is a statically typed superset of JavaScript that compiles to plain JavaScript. When used with React, it can dramatically improve the developer experience and help you build more robust, error-free applications. By adding a type system, TypeScript allows you to catch common errors during development—before your code ever runs—rather than encountering them at runtime. This "shift-left" approach to bug-finding leads to higher quality code, easier refactoring, and better team collaboration, especially on large-scale projects.

While it might seem like extra work initially, adding types to your React project provides excellent autocompletion and documentation right in your editor. This self-documenting nature makes components' APIs explicit and prevents common bugs, such as passing the wrong type of data in props or mismanaging state. It's an investment that pays huge dividends in maintainability and developer confidence.

Typing Component Props

One of the most immediate and impactful benefits of TypeScript is the ability to strongly type your component props. You define the expected "shape" of the props object using an interface or a type alias. This ensures that any time you use the component, you provide all the required props with the correct data types. You can also specify optional props with a ?.


// Define the shape of the props for a UserProfile component
interface UserProfileProps {
  name: string;
  age: number;
  isLoggedIn: boolean;
  bio?: string; // Optional prop
}

// Use the type for your component's props with React.FC (Functional Component)
const UserProfile: React.FC = ({ name, age, isLoggedIn, bio }) => {
  if (!isLoggedIn) {
    return <p>Please log in to view this profile.</p>;
  }
  return (
    <div>
      <h2>Welcome, {name}</h2>
      <p>Age: {age}</p>
      {bio && <p>Bio: {bio}</p>}
    </div>
  );
};
      

Now, if you try to use <UserProfile name="John" isLoggedIn={true} /> without the required `age` prop, TypeScript will immediately show an error in your editor, preventing a potential runtime bug. The React.FC type also provides type-checking for standard component properties like children.

Typing State and Events

TypeScript's power extends to state management and event handling. When using the useState hook, TypeScript can often infer the type from the initial value. However, for more complex state or when the initial state is null/undefined, you can be explicit.


import React, { useState } from 'react';

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

function UserData() {
  // Explicitly type the state. It can be a User object or null.
  const [user, setUser] = useState(null);

  const handleLogin = () => {
    setUser({ id: 1, name: 'Jane Doe' });
  };
  
  if (!user) {
    return <button onClick={handleLogin}>Login</button>;
  }
  
  return <div>Welcome, {user.name}</div>;
}
      

Common Event Types in React

Event Type Element Example
React.ChangeEvent<HTMLInputElement> <input>
React.ChangeEvent<HTMLTextAreaElement> <textarea>
React.MouseEvent<HTMLButtonElement> <button>
React.FormEvent<HTMLFormElement> <form> (for onSubmit)

Embracing TypeScript in your React projects is a significant step towards professional-grade application development. It enforces discipline, improves code quality, and ultimately makes the development process faster and more enjoyable by eliminating a whole class of common errors.

10 Common TypeScript-React Errors and Their Fixes

Integrating TypeScript with React is a game-changer, but it introduces a new set of challenges. Here are 10 common errors and how to fix them.

# Common Error Why It Happens Solution
1 "Property 'x' does not exist on type 'IntrinsicAttributes & { ... }'." You are passing a prop to a component that hasn't been defined in the component's prop types (interface or type). Add the missing property to the component's props interface. E.g., interface MyComponentProps { x: string; }.
2 "Type 'null' is not assignable to type 'User'." Your state is initialized with null, but the type for useState doesn't include null. Use a union type for your state: useState<User | null>(null).
3 "Object is possibly 'null' or 'undefined'." You are trying to access a property on a variable that could be null or undefined at runtime. Use optional chaining (user?.name) or add a type guard to ensure the object exists before accessing it (if (user) { ... }).
4 Event Type Errors (e.g., on event.target.value) The event object is not correctly typed, so TypeScript doesn't know about properties like target.value. Provide the correct event type for your handler. For an input's onChange, use React.ChangeEvent<HTMLInputElement>.
5 Implicit any type. A function parameter or variable has no type annotation and TypeScript cannot infer it, so it defaults to any, which disables type checking. Enable "noImplicitAny": true in your tsconfig.json and provide explicit types for all parameters and variables.
6 Typing children prop. You want your component to accept children, but you haven't typed the children prop. Use React.PropsWithChildren<MyProps> or add children: React.ReactNode to your props interface. React.FC includes this by default.
7 Generic component prop errors. Creating a generic component (like a list or table) without correctly passing down generic types can lead to a loss of type safety. Define your component with a generic type parameter. E.g., function List<T>({ items, renderItem }: ListProps<T>) { ... }.
8 "Type 'string' is not assignable to type '"option1" | "option2"'." You are trying to pass a generic string to a prop that expects a specific union of string literals. Ensure the value you are passing matches one of the exact string values in the union type. If the value is dynamic, you may need to use a type assertion (e.g., value as MyUnionType), but do this with caution.
9 Struggling with third-party library types. A library may not have built-in types or its types are incorrect. Check if there's a corresponding @types/<library-name> package to install. If not, you can declare your own types in a .d.ts file.
10 Overly complex or nested types. Sometimes types can become so complex (e.g., deep objects with many generics) that they are hard to read and maintain. Break down complex types into smaller, reusable type or interface definitions. Give them clear, semantic names to improve readability.