Lesson 55 of 60 – Typing React Props
92%

Typing React Props

Props are values passed from a parent React component to a child component. In TypeScript, props can be typed using interfaces or type aliases so that components receive the correct kind of data.

Note: Properly typed props make React components easier to understand, reuse, and maintain. TypeScript can detect many incorrect prop values during development.

1. What are Props?

Props are data passed from a parent component to a child component.

function Welcome(props) {
    return <h1>Hello {props.name}</h1>;
}

Here, name is a prop.

2. Why Type React Props?

TypeScript allows us to specify what data a component expects.

  • Prevents incorrect data types.
  • Improves editor suggestions.
  • Makes components easier to understand.
  • Improves reusable component development.
  • Helps catch mistakes during development.

3. Basic Props Type

interface UserProps {
    name: string;
}

function User(props: UserProps) {
    return <h2>{props.name}</h2>;
}

The component expects a name prop of type string.

4. Passing String Props

<User name="Rahul" />

The value "Rahul" is a string, so it matches the defined prop type.

5. Number Props

interface StudentProps {
    age: number;
}

function Student({
    age
}: StudentProps) {
    return <p>Age: {age}</p>;
}

The age prop must be a number.

6. Passing Number Props

<Student age={20} />

Curly braces are used to pass a JavaScript or TypeScript expression such as a number.

7. Boolean Props

interface ButtonProps {
    disabled: boolean;
}

function Button({
    disabled
}: ButtonProps) {

    return (
        <button disabled={disabled}>
            Submit
        </button>
    );
}

8. Passing Boolean Props

<Button disabled={true} />

Boolean values are normally passed inside curly braces.

9. Multiple Props

interface StudentProps {
    name: string;
    age: number;
    course: string;
}

function Student({
    name,
    age,
    course
}: StudentProps) {

    return (
        <div>
            <h2>{name}</h2>
            <p>Age: {age}</p>
            <p>Course: {course}</p>
        </div>
    );
}

10. Passing Multiple Props

<Student
    name="Rahul"
    age={20}
    course="React Native"
/>

All required props must be supplied.

11. Required Props

A prop is required when it does not have the ? symbol.

interface UserProps {
    name: string;
    email: string;
}

Both name and email are required.

12. Optional Props

Add ? after a property name to make the prop optional.

interface UserProps {
    name: string;
    email?: string;
}

The component can be used without providing email.

13. Default Value for Optional Props

interface UserProps {
    name: string;
    age?: number;
}

function User({
    name,
    age = 18
}: UserProps) {

    return (
        <p>
            {name} - {age}
        </p>
    );
}

14. Props with Type Alias

A type alias can also be used to define component props.

type UserProps = {
    name: string;
    age: number;
};

function User({
    name,
    age
}: UserProps) {

    return (
        <h2>
            {name} - {age}
        </h2>
    );
}

15. Object Props

interface Student {
    id: number;
    name: string;
    course: string;
}

interface StudentProps {
    student: Student;
}

function StudentCard({
    student
}: StudentProps) {

    return (
        <div>
            <h2>{student.name}</h2>
            <p>ID: {student.id}</p>
            <p>Course: {student.course}</p>
        </div>
    );
}

16. Passing an Object as a Prop

const student = {
    id: 101,
    name: "Rahul",
    course: "TypeScript"
};

<StudentCard student={student} />

The object must match the Student type.

17. Array Props

interface StudentListProps {
    students: string[];
}

function StudentList({
    students
}: StudentListProps) {

    return (
        <ul>
            {students.map((student) =>
                <li key={student}>
                    {student}
                </li>
            )}
        </ul>
    );
}

18. Object Array Props

interface Student {
    id: number;
    name: string;
}

interface StudentListProps {
    students: Student[];
}

function StudentList({
    students
}: StudentListProps) {

    return (
        <div>
            {students.map((student) => (
                <p key={student.id}>
                    {student.name}
                </p>
            ))}
        </div>
    );
}

19. Function Props

Functions can be passed as props to allow a child component to trigger an action in the parent.

interface ButtonProps {
    onClick: () => void;
}

function Button({
    onClick
}: ButtonProps) {

    return (
        <button onClick={onClick}>
            Click
        </button>
    );
}

20. Function Props with Parameters

interface UserProps {
    onSelect: (id: number) => void;
}

function UserButton({
    onSelect
}: UserProps) {

    return (
        <button
            onClick={() => onSelect(101)}
        >
            Select User
        </button>
    );
}

21. Props with ReactNode

ReactNode can be used when a component needs to accept React content such as text or JSX.

import { ReactNode } from "react";

interface CardProps {
    children: ReactNode;
}

function Card({
    children
}: CardProps) {

    return (
        <div>
            {children}
        </div>
    );
}

22. Using children as Props

<Card>
    <h2>Student Details</h2>
    <p>Welcome to React.</p>
</Card>

The content between the opening and closing component tags is received through children.

23. Readonly Props

TypeScript can use readonly properties to prevent reassignment through that typed reference.

interface UserProps {
    readonly id: number;
    name: string;
}

function User({
    id,
    name
}: UserProps) {

    return (
        <div>
            <p>ID: {id}</p>
            <p>Name: {name}</p>
        </div>
    );
}

24. Union Type Props

A prop can accept more than one type using a union type.

interface MessageProps {
    value: string | number;
}

function Message({
    value
}: MessageProps) {

    return <p>{value}</p>;
}

25. Literal Type Props

Literal types can restrict a prop to specific values.

interface ButtonProps {
    type: "primary" | "secondary";
}

function Button({
    type
}: ButtonProps) {

    return (
        <button className={type}>
            Button
        </button>
    );
}

26. Props and Event Handlers

Event handler functions can be passed as typed props.

interface ButtonProps {
    onClick: (
        event: React.MouseEvent<HTMLButtonElement>
    ) => void;
}

function Button({
    onClick
}: ButtonProps) {

    return (
        <button onClick={onClick}>
            Click Me
        </button>
    );
}

27. Reusable Typed Card Component

interface CardProps {
    title: string;
    description: string;
}

function Card({
    title,
    description
}: CardProps) {

    return (
        <div>
            <h2>{title}</h2>
            <p>{description}</p>
        </div>
    );
}

<Card
    title="TypeScript"
    description="Learn TypeScript with React"
/>

28. Parent to Child Data Flow

React normally follows a one-way data flow where the parent passes data to the child through props.

function Parent() {

    const name = "Rahul";

    return (
        <Child name={name} />
    );
}

interface ChildProps {
    name: string;
}

function Child({
    name
}: ChildProps) {

    return <h2>Hello {name}</h2>;
}

29. Common Props Typing Mistakes

  • Forgetting to define required props.
  • Passing a string where a number is expected.
  • Passing a number where a boolean is expected.
  • Forgetting ? for optional props.
  • Using an incorrect function parameter type.
  • Passing an object that does not match the expected structure.
  • Using an incorrect type for children.

30. Complete Typed Props Example

import { ReactNode } from "react";

interface Student {
    id: number;
    name: string;
    course: string;
}

interface StudentCardProps {
    student: Student;
    onSelect: (id: number) => void;
    children?: ReactNode;
}

function StudentCard({
    student,
    onSelect,
    children
}: StudentCardProps) {

    return (
        <div>

            <h2>
                {student.name}
            </h2>

            <p>
                ID: {student.id}
            </p>

            <p>
                Course: {student.course}
            </p>

            {children}

            <button
                onClick={() =>
                    onSelect(student.id)
                }
            >
                Select Student
            </button>

        </div>
    );
}

function App() {

    const student: Student = {
        id: 101,
        name: "Rahul",
        course: "React Native"
    };

    const handleSelect = (id: number): void => {
        console.log(
            "Selected Student:",
            id
        );
    };

    return (
        <StudentCard
            student={student}
            onSelect={handleSelect}
        >

            <p>
                Student information
            </p>

        </StudentCard>
    );
}

export default App;

This example combines object props, function props, optional children, interfaces, and event handling in one reusable React component.

📌 Key Points

  • Props are used to pass data from parent to child components.
  • TypeScript allows us to define the type of each prop.
  • Interfaces and type aliases can be used to define props.
  • Props without ? are required.
  • Props with ? are optional.
  • String, number, boolean, array, and object props can be typed.
  • Functions can be passed as typed props.
  • ReactNode can be used for children content.
  • Union and literal types can make props more specific.
  • Properly typed props make reusable components safer and easier to maintain.

🧠 Quick Quiz

Question: Which TypeScript symbol is used to make a React prop optional?