React TypeScript Best Practices: Complete Guide for Type-Safe React Applications

#typescript #react #typesafety #webdev
React TypeScript Best Practices: Complete Guide for Type-Safe React Applications

When I first started using TypeScript with React, I thought it would just add extra typing overhead. Boy, was I wrong. TypeScript has saved me countless hours by catching bugs before they reach production, and it’s made my codebase infinitely more maintainable. But using TypeScript effectively in React requires understanding some patterns and best practices that aren’t always obvious.

TypeScript brings compile-time type checking to React, which means you catch errors while writing code, not when users report bugs. It also provides incredible IDE support - autocomplete, refactoring, and navigation all work better when TypeScript understands your code structure. But to get these benefits, you need to type your components, props, hooks, and event handlers correctly.


Why TypeScript with React?

TypeScript with React provides:

  • Type safety - Catch errors at compile time
  • Better IDE support - Autocomplete, IntelliSense, and refactoring
  • Self-documenting code - Types serve as documentation
  • Easier refactoring - TypeScript catches breaking changes
  • Better collaboration - Types help team members understand code
  • Runtime error prevention - Catch bugs before they reach production

Type Definitions for Props

Define component prop types using interfaces or types:

type Product = {
  id: string | number;
  name: string;
  price: number;
  stock: number;
  categoryId: number;
  categoryName?: string;
};

interface ProductCardProps {
  product: Product;
  onEdit?: (id: string | number) => void;
  onDelete?: (id: string | number) => void;
  showActions?: boolean;
}

function ProductCard({ 
  product, 
  onEdit, 
  onDelete, 
  showActions = true 
}: ProductCardProps) {
  return (
    <div className="product-card">
      <h3>{product.name}</h3>
      <p>${product.price}</p>
      <p>Stock: {product.stock}</p>
      {showActions && (
        <div>
          {onEdit && <button onClick={() => onEdit(product.id)}>Edit</button>}
          {onDelete && <button onClick={() => onDelete(product.id)}>Delete</button>}
        </div>
      )}
    </div>
  );
}

Typing React Hooks

useState Hook

Type useState explicitly or let TypeScript infer:

// Explicit typing
const [name, setName] = useState<string>("");
const [count, setCount] = useState<number>(0);
const [products, setProducts] = useState<Product[]>([]);

// Type inference
const [isLoading, setIsLoading] = useState(false); // boolean
const [user, setUser] = useState<User | null>(null); // Better

Custom Hooks

Create typed custom hooks:

type UseProductsReturn = {
  products: Product[];
  isLoading: boolean;
  isError: boolean;
  error: any;
  refetch: () => void;
};

function useProducts(): UseProductsReturn {
  const { data, isLoading, isError, error, refetch } = useGetProductsQuery({});

  return {
    products: data?.data || [],
    isLoading,
    isError,
    error,
    refetch,
  };
}

Event Handlers

Type event handlers correctly:

// Form submit handler
const handleSubmit = (e: React.FormEvent<HTMLFormElement>) => {
  e.preventDefault();
  // Handle submission
};

// Button click handler
const handleClick = (e: React.MouseEvent<HTMLButtonElement>) => {
  // Handle click
};

// Input change handler
const handleChange = (e: React.ChangeEvent<HTMLInputElement>) => {
  setValue(e.target.value);
};

Best Practices

  1. Use interfaces for component props
  2. Type useState explicitly when needed
  3. Create typed custom hooks
  4. Type event handlers correctly
  5. Use generics for reusable components
  6. Leverage type inference when possible

Going Further

This is just a brief overview. For a complete guide covering generics, context types, ref types, higher-order components, and advanced patterns like utility types and conditional types, check out the full article with real-world examples from production applications.

What’s your experience with TypeScript and React? Share your tips!

Tools & Technologies I Use

React
Next.js
Vue
Angular
Svelte
React Native
Tailwind CSS
CSS3
Sass/SCSS
Bootstrap
Styled Components
Framer Motion
Vite
Webpack
npm
pnpm
React
Next.js
Vue
Angular
Svelte
React Native
Tailwind CSS
CSS3
Sass/SCSS
Bootstrap
Styled Components
Framer Motion
Vite
Webpack
npm
pnpm
Yarn
Jest
Cypress
Storybook
Vitest
Node.js
Prisma
PostgreSQL
MongoDB
Supabase
Firebase
Vercel
Coolify
Git
TypeScript
GraphQL
Yarn
Jest
Cypress
Storybook
Vitest
Node.js
Prisma
PostgreSQL
MongoDB
Supabase
Firebase
Vercel
Coolify
Git
TypeScript
GraphQL

Let's work together.

©2026. Designed by Ivan Radoš - Powered by Marko Arthofer