As a React developer, I have seen many developers struggle with passing data between components.
When I first started, we used PropTypes, which worked, but it often felt like we were catching errors too late in the process.
Transitioning to TypeScript changed everything for me, especially when it comes to defining component parameters (or “props”).
Using TypeScript with React ensures that your components are predictable, easier to debug, and much more scalable.
In this tutorial, I will show you exactly how to handle React component parameters using TypeScript, using real-world examples you would actually see in a professional project.
Use TypeScript for React Component Parameters
Before we jump into the code, let’s talk about why this matters from a developer’s perspective.
When you define parameters with TypeScript, your editor provides instant feedback and autocomplete.
If you try to pass a string where a number is expected, you’ll see a red underline immediately, not a crash in the browser.
Method 1: Use Interfaces for Functional Components
This is my go-to method for most professional React projects. It keeps the component signature clean.
Interfaces allow you to define the shape of your props object clearly before you even write the component logic.
Let’s look at an example of a “Salary Calculator” component, something very common in US-based fintech applications.
import React from 'react';
// Defining the interface for our component parameters
interface SalaryDetailsProps {
employeeName: string;
annualSalary: number;
state: 'NY' | 'CA' | 'TX' | 'FL'; // Restricted to specific US states
isExempt: boolean;
}
const SalaryDetails: React.FC<SalaryDetailsProps> = ({
employeeName,
annualSalary,
state,
isExempt
}) => {
const monthlyPay = (annualSalary / 12).toLocaleString('en-US', {
style: 'currency',
currency: 'USD',
});
return (
<div style={{ padding: '20px', border: '1px solid #ccc', borderRadius: '8px' }}>
<h2>Payroll Entry: {employeeName}</h2>
<p>Base Monthly Pay: {monthlyPay}</p>
<p>Tax Jurisdiction: {state}</p>
<p>Employment Status: {isExempt ? 'Exempt (Salary)' : 'Non-Exempt (Hourly)'}</p>
</div>
);
};
// Usage Example
export default function PayrollApp() {
return (
<SalaryDetails
employeeName="John Doe"
annualSalary={125000}
state="NY"
isExempt={true}
/>
);
}You can refer to the screenshot below to see the output.

In this example, I used an interface to define exactly what the component needs. If you forget to pass the state prop, TypeScript will throw an error immediately.
Method 2: Handle Optional Parameters
In many real-world scenarios, not every piece of data is required. For example, a US shipping address might include an optional “Apartment/Suite” line.
In TypeScript, we use the ? symbol to mark a parameter as optional.
import React from 'react';
interface ShippingLabelProps {
recipientName: string;
streetAddress: string;
secondaryAddress?: string; // This is optional
city: string;
zipCode: string;
}
const ShippingLabel: React.FC<ShippingLabelProps> = ({
recipientName,
streetAddress,
secondaryAddress,
city,
zipCode
}) => {
return (
<div style={{ backgroundColor: '#f9f9f9', padding: '15px', width: '300px' }}>
<h3>Ship To:</h3>
<p><strong>{recipientName}</strong></p>
<p>{streetAddress}</p>
{secondaryAddress && <p>{secondaryAddress}</p>}
<p>{city}, {zipCode}</p>
<p>United States</p>
</div>
);
};
// Usage with and without optional props
export const ShippingDashboard = () => {
return (
<div>
{/* Example with optional secondary address */}
<ShippingLabel
recipientName="Alice Smith"
streetAddress="123 Wall Street"
secondaryAddress="Suite 500"
city="New York"
zipCode="10005"
/>
{/* Example without optional secondary address */}
<ShippingLabel
recipientName="Bob Jones"
streetAddress="456 Maple Avenue"
city="Austin"
zipCode="73301"
/>
</div>
);
};I find that using optional props makes components much more reusable across different parts of an application.
Method 3: Pass Functions as Parameters
In React, we often need to pass functions (like event handlers) from a parent to a child.
This is a core concept for “Lifting State Up.” In TypeScript, we must define the function’s signature.
Let’s build a simple “Tax Credit Toggle” used in US tax preparation software.
import React, { useState } from 'react';
interface TaxToggleProps {
label: string;
onToggle: (isActive: boolean) => void; // A function that takes a boolean and returns nothing
}
const TaxToggle: React.FC<TaxToggleProps> = ({ label, onToggle }) => {
return (
<div style={{ margin: '10px 0' }}>
<span>{label}</span>
<button onClick={() => onToggle(true)}>Enable</button>
<button onClick={() => onToggle(false)}>Disable</button>
</div>
);
};
export const TaxForm = () => {
const [hasChildTaxCredit, setHasChildTaxCredit] = useState(false);
const handleToggle = (status: boolean) => {
setHasChildTaxCredit(status);
console.log(`Tax Credit Status Changed: ${status}`);
};
return (
<div>
<h1>IRS Form 1040 Assistant</h1>
<TaxToggle
label="Child Tax Credit (CTC)"
onToggle={handleToggle}
/>
<p>Status: {hasChildTaxCredit ? 'Applied' : 'Not Applied'}</p>
</div>
);
};Defining the function type in the interface prevents you from accidentally passing the wrong function or calling it with the wrong arguments.
Method 4: Use Union Types for Specific Values
Sometimes you want to limit a parameter to a set of specific strings.
This is incredibly useful for US-based apps dealing with time zones or credit card types.
import React from 'react';
interface PaymentCardProps {
cardHolder: string;
cardType: 'Visa' | 'MasterCard' | 'Amex' | 'Discover'; // Union Type
lastFour: string;
}
const PaymentCard: React.FC<PaymentCardProps> = ({ cardHolder, cardType, lastFour }) => {
return (
<div style={{ border: '1px solid black', padding: '10px', width: '250px' }}>
<p>{cardType} ending in ****{lastFour}</p>
<small>{cardHolder}</small>
</div>
);
};
export const CheckoutPage = () => {
return (
<PaymentCard
cardHolder="Michael Scott"
cardType="Amex" // TypeScript ensures we can't type "ApplePay" here
lastFour="9876"
/>
);
};I use Union types daily to ensure that only valid business logic values are passed through my components.
Method 5: Children Props and ReactNode
Sometimes your component acts as a wrapper or a container. In these cases, you need to pass React elements as parameters.
The children prop is a special parameter in React. In TypeScript, we usually type it as React.ReactNode.
import React, { ReactNode } from 'react';
interface ModalLayoutProps {
title: string;
children: ReactNode; // Allows any valid React element
}
const ModalLayout: React.FC<ModalLayoutProps> = ({ title, children }) => {
return (
<div className="modal-overlay" style={{ background: '#eee', padding: '20px' }}>
<div className="modal-content" style={{ background: '#fff', padding: '20px' }}>
<h1>{title}</h1>
<hr />
<div className="body-content">
{children}
</div>
</div>
</div>
);
};
export const Dashboard = () => {
return (
<ModalLayout title="US Market Summary">
<p>The S&P 500 is up by 1.2% today.</p>
<button>View Full Report</button>
</ModalLayout>
);
};Using ReactNode is the most flexible way to pass nested components and HTML elements.
Common Mistakes to Avoid
In my experience, even seasoned developers make a few common mistakes when typing props.
First, avoid using the any type at all costs. It defeats the entire purpose of using TypeScript.
Second, don’t over-complicate your interfaces. If an interface gets too large, it might be a sign that your component is doing too much.
Lastly, remember to export your interfaces if you plan to use them in unit tests or other components.
Defining parameters correctly is the backbone of a maintainable React codebase.
It makes the developer experience much smoother and prevents common runtime errors that can frustrate users.
I hope you found this tutorial helpful! Using TypeScript with React is one of the best decisions you can make for your professional growth.
You may also like to read:
- How to Use TableSortLabel in React MUI
- How to Implement TablePagination in React MUI Tables
- How to Build a Sortable and Paginated Table in React MUI
- How to Build a Custom Table Component in React MUI
- How to Get Component Height in React

I am Bijay Kumar, a Microsoft MVP in SharePoint. Apart from SharePoint, I started working on Python, Machine learning, and artificial intelligence for the last 5 years. During this time I got expertise in various Python libraries also like Tkinter, Pandas, NumPy, Turtle, Django, Matplotlib, Tensorflow, Scipy, Scikit-Learn, etc… for various clients in the United States, Canada, the United Kingdom, Australia, New Zealand, etc. Check out my profile.