🟦 React with TypeScript
Estimated reading: 4 minutes 31 views

🟦 React Typing Props & State – Write Safer Components with TypeScript (2025 Guide)


🧲 Introduction – Why Type Props & State in React?

In React.js, props and state are essential for component behavior and rendering. By using TypeScript, you bring type safety to these data structures, helping:

  • πŸ”’ Prevent runtime bugs
  • 🧠 Enable powerful IntelliSense/autocomplete
  • βœ… Document component APIs with explicit typings

Whether you’re working with form data, UI toggles, or complex nested props, typing them ensures your components are predictable, maintainable, and scalable.

🎯 In this guide, you’ll learn:

  • How to type props and state in functional components
  • Use optional, union, and nested props
  • Type useState, event handlers, and object states
  • Best practices for reusable prop types

🧱 1. Typing Props in Functional Components

βœ… Example: Basic Props

type GreetingProps = {
  name: string;
  age?: number; // optional
};

const Greeting = ({ name, age }: GreetingProps) => (
  <p>Hello, {name}! {age && `(Age: ${age})`}</p>
);

πŸ“˜ GreetingProps defines what data the component expects
βœ… Helps catch prop misuse early


βœ… With React.FC (FunctionComponent)

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

⚠️ React.FC automatically types children but adds overheadβ€”prefer plain function types for performance-critical code.


πŸ”„ 2. Typing Component State with useState

βœ… Simple State:

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

βœ… Object State:

type FormState = {
  username: string;
  email: string;
};

const [form, setForm] = useState<FormState>({
  username: '',
  email: '',
});

βœ… Keep object state type-safe
πŸ“˜ Type useState<T>() to define the structure


πŸ“¦ 3. Optional & Default Props

type ButtonProps = {
  label: string;
  variant?: 'primary' | 'secondary';
};

const Button = ({ label, variant = 'primary' }: ButtonProps) => (
  <button className={variant}>{label}</button>
);

βœ… Use ? for optional props
βœ… Provide default values in the function body


🧠 4. Event Handlers Typing

βœ… Input Change Event:

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

βœ… Button Click Event:

const handleClick = (e: React.MouseEvent<HTMLButtonElement>) => {
  console.log('Clicked!', e.currentTarget);
};

πŸ“˜ Use React.Event, React.ChangeEvent, React.MouseEvent, etc.


🧩 5. Typing Props with Children

type CardProps = {
  title: string;
  children: React.ReactNode;
};

const Card = ({ title, children }: CardProps) => (
  <div className="card">
    <h2>{title}</h2>
    {children}
  </div>
);

βœ… React.ReactNode supports text, elements, fragments, arrays, etc.


πŸ” 6. Reusable Prop Patterns with Union & Enums

βœ… Union Props:

type AlertProps =
  | { type: 'success'; message: string }
  | { type: 'error'; errorCode: number };

const Alert = (props: AlertProps) => {
  if (props.type === 'success') return <p>{props.message}</p>;
  return <p>Error Code: {props.errorCode}</p>;
};

βœ… Enum Props:

enum Variant {
  Primary = 'primary',
  Secondary = 'secondary',
}

type ButtonProps = {
  label: string;
  variant: Variant;
};

πŸ“˜ Use union types for conditional rendering
βœ… Use enums when values are shared across components


πŸ§ͺ 7. Typing Props for Custom Hooks

type ToggleHook = [boolean, () => void];

function useToggle(initial: boolean): ToggleHook {
  const [on, setOn] = useState(initial);
  const toggle = () => setOn(prev => !prev);
  return [on, toggle];
}

βœ… Clear return types enhance reusability
βœ… Useful when sharing state logic across multiple components


πŸ“˜ Best Practices

PracticeWhy It Helps
βœ… Use type or interfaceMakes components self-documenting
βœ… Always annotate useState for non-primitivesPrevents inference issues
βœ… Use union types for conditional propsEnforces stricter usage
βœ… Keep prop types small & reusableImproves readability and reuse
βœ… Avoid any unless absolutely neededMaintain type safety and clarity

πŸ“Œ Summary – Recap & Next Steps

Typing props and state in React with TypeScript helps you build stable, self-documenting components. You gain better autocomplete, validation, and early error detectionβ€”all of which help scale your project with confidence.

πŸ” Key Takeaways:

  • Use type/interface to define prop and state shapes
  • Annotate useState when dealing with objects, nulls, or arrays
  • Use React.ChangeEvent, React.MouseEvent for event handlers
  • Pass children using React.ReactNode
  • Use union types or enums for component variants

βš™οΈ Real-World Relevance:
Used in large TypeScript codebases like Shopify Polaris, Radix UI, and Microsoft Fabric to deliver type-safe and reusable components.


❓ FAQ Section

❓ What’s the difference between type and interface?
βœ… Both can define shapes. Prefer type for union/intersections and interface for extending object contracts.


❓ Do I need to type state if it’s a number or string?
βœ… Not always. TypeScript can infer simple types, but use explicit types for objects or when initializing to null.


❓ Can I type default props?
βœ… Yes. Provide defaults in the function body and mark them as optional (prop?: string).


❓ How do I avoid repeating prop types in multiple files?
βœ… Export shared types into a /types folder and import as needed:

import { ButtonProps } from '@/types/button';

❓ How to type children correctly in React?
βœ… Use React.ReactNode or ReactElement depending on flexibility:

type Props = { children: React.ReactNode };

Share Now :

Leave a Reply

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

Share

🟦 React Typing Props & State

Or Copy Link

CONTENTS
Scroll to Top