Skip to main content
Back to Blog

TypeScript Best Practices for React Applications

Explore essential TypeScript patterns and best practices that will make your React applications more maintainable and type-safe.

TypeScript, React, Best Practices

TypeScript Best Practices for React Applications

TypeScript has revolutionized the way we build React applications. In this post, I'll share some essential patterns and best practices I've learned.

Why TypeScript with React?

TypeScript brings several benefits to React development:

  • Type Safety: Catch errors before runtime
  • Better IDE Support: Autocomplete, refactoring, and navigation
  • Self-Documenting Code: Types serve as inline documentation
  • Easier Refactoring: Confidence when making changes

Component Props

Always define your component props with interfaces:

interface ButtonProps {
  variant?: 'primary' | 'secondary';
  size?: 'sm' | 'md' | 'lg';
  onClick?: () => void;
  children: React.ReactNode;
}

export function Button({ 
  variant = 'primary', 
  size = 'md', 
  onClick, 
  children 
}: ButtonProps) {
  return (
    <button 
      className={`btn-${variant} btn-${size}`}
      onClick={onClick}
    >
      {children}
    </button>
  );
}

State Management

Use proper typing for state:

interface User {
  id: string;
  name: string;
  email: string;
}

function UserProfile() {
  const [user, setUser] = useState<User | null>(null);
  const [loading, setLoading] = useState<boolean>(false);
  
  // Your component logic here
}

Event Handlers

Type your event handlers correctly:

function handleChange(event: React.ChangeEvent<HTMLInputElement>) {
  console.log(event.target.value);
}

function handleSubmit(event: React.FormEvent<HTMLFormElement>) {
  event.preventDefault();
  // Handle form submission
}

Custom Hooks

Create reusable, type-safe hooks:

function useLocalStorage<T>(key: string, initialValue: T) {
  const [value, setValue] = useState<T>(() => {
    const item = localStorage.getItem(key);
    return item ? JSON.parse(item) : initialValue;
  });

  const setStoredValue = (newValue: T) => {
    setValue(newValue);
    localStorage.setItem(key, JSON.stringify(newValue));
  };

  return [value, setStoredValue] as const;
}

Utility Types

Leverage TypeScript's utility types:

// Pick specific properties
type UserPreview = Pick<User, 'id' | 'name'>;

// Make all properties optional
type PartialUser = Partial<User>;

// Make all properties required
type RequiredUser = Required<User>;

// Omit specific properties
type UserWithoutEmail = Omit<User, 'email'>;

Conclusion

These TypeScript patterns will help you write more maintainable and type-safe React applications. Remember to always leverage TypeScript's type system to its full potential!


Share this post