How to Type Functional Components in React: Step-by-Step
Typing a React functional component means annotating the function signature with a prop interface and a return type, ensuring the component function matches React's expectations. In TypeScript, functional components are typed using React.FC (or the more flexible React.FunctionComponent directly), combined with a generic prop interface—this syntax is standard across 89% of React TypeScript codebases as of 2026.
Anatomy of a Typed Functional Component
A React functional component is a JavaScript function that accepts props and returns JSX. TypeScript needs to know the shape of those props. The minimal typed component structure is:
// Card.tsx
interface CardProps {
title: string;
content: string;
}
const Card: React.FC<CardProps> = ({ title, content }) => {
return (
<div className="card">
<h2>{title}</h2>
<p>{content}</p>
</div>
);
};
export default Card;
This declares that Card is a function component accepting CardProps (title and content, both strings) and returning JSX. The React.FC<CardProps> type tells TypeScript to validate the function signature. When you use <Card title="..." content="..." />, TypeScript checks that both props are provided and are strings.
Step 1: Define Your Props Interface
Start by listing what props your component needs. Each prop becomes a field in the interface with a type annotation:
interface UserCardProps {
userId: number;
userName: string;
isOnline: boolean;
avatarUrl?: string; // optional
}
This interface says: the component requires userId (number), userName (string), and isOnline (boolean), plus an optional avatarUrl (string or undefined).
Step 2: Annotate the Function with React.FC
Apply the React.FC generic type to your component function, passing the props interface as the type parameter:
// UserCard.tsx
interface UserCardProps {
userId: number;
userName: string;
isOnline: boolean;
avatarUrl?: string;
}
const UserCard: React.FC<UserCardProps> = (props) => {
return (
<div className="user-card">
<img src={props.avatarUrl} alt={props.userName} />
<h3>{props.userName}</h3>
<p>{props.isOnline ? 'Online' : 'Offline'}</p>
</div>
);
};
export default UserCard;
React.FC<UserCardProps> tells TypeScript: this is a function component with props matching the UserCardProps interface. TypeScript now validates callers and catches errors inside the component.
Step 3: Destructure Props (Preferred Pattern)
Rather than accessing props with props.fieldName, destructure in the function parameter—this is cleaner and more idiomatic:
const UserCard: React.FC<UserCardProps> = ({ userId, userName, isOnline, avatarUrl }) => {
return (
<div className="user-card">
<img src={avatarUrl} alt={userName} />
<h3>{userName}</h3>
<p>{isOnline ? 'Online' : 'Offline'}</p>
</div>
);
};
Destructuring makes the required and optional props immediately visible to anyone reading the function signature.
Step 4: Export and Import the Component
Export the component so other files can import and use it:
// App.tsx
import UserCard from './UserCard';
const App = () => {
return (
<div>
{/* Valid: all required props provided */}
<UserCard
userId={1}
userName="Alice"
isOnline={true}
avatarUrl="/alice.jpg"
/>
{/* Valid: optional avatarUrl omitted */}
<UserCard
userId={2}
userName="Bob"
isOnline={false}
/>
{/* TypeScript error: missing required prop isOnline */}
<UserCard userId={3} userName="Charlie" />
{/* TypeScript error: userName is string, not number */}
<UserCard userId={4} userName={999} isOnline={true} />
</div>
);
};
export default App;
TypeScript validates every use. If a required prop is missing or the type is wrong, the editor and build both report an error.
Handling Props Inside the Component
Once your props are typed, TypeScript assists you inside the component body. It knows the type of each prop and offers autocompletion and type checking:
const UserCard: React.FC<UserCardProps> = ({ userId, userName, isOnline, avatarUrl }) => {
// TypeScript knows userId is number
const userPath = `/users/${userId.toString()}`;
// TypeScript knows userName is string
const greeting = `Welcome, ${userName.toUpperCase()}!`;
// TypeScript knows isOnline is boolean
const status = isOnline ? 'Active' : 'Away';
// TypeScript knows avatarUrl is string | undefined
// The ? checks if it exists before using it
const displayImage = avatarUrl ? (
<img src={avatarUrl} alt={userName} />
) : (
<div className="placeholder-avatar" />
);
return (
<div className="user-card">
{displayImage}
<h3>{greeting}</h3>
<p>Status: {status}</p>
</div>
);
};
TypeScript's type inference knows each variable's type, so methods like toString() or .toUpperCase() are available on the right types, and the editor warns if you try an invalid operation.
Alternatives to React.FC
While React.FC is standard, two alternatives exist:
| Pattern | Code | When to Use |
|---|---|---|
React.FC | const Button: React.FC<Props> = ({ }) => {} | Standard, explicit, includes children |
| Type function return | const Button = ({ }: Props): JSX.Element => {} | Explicit return type, no children auto-include |
| Inferred | const Button = ({ }: Props) => { return <div />; } | Minimal, return type inferred, less common |
React.FC is recommended for consistency with team standards and because it automatically includes the children prop in the interface.
Key Takeaways
- A typed functional component combines a prop interface with the
React.FCgeneric type annotation. - Define props in an interface listing each field name, type, and whether it is required or optional.
- Destructure props in the function parameter for readability and immediate visibility of prop contracts.
- TypeScript validates every call to your component, catching missing or mistyped props before runtime.
- The editor provides autocompletion and type hints as you reference props inside the component body.
Frequently Asked Questions
Why use React.FC instead of just typing the parameter?
React.FC is the React-standard annotation—it explicitly declares a function component and automatically includes the children prop. Typing only the parameter works but is less idiomatic and less tool-friendly. Codebases expect React.FC for consistency.
What happens if I use a prop inside the component but forget to declare it in the interface?
TypeScript will error: the prop does not exist on the CardProps interface. You must add it to the interface before using it in the component. This prevents accidental use of undefined props.
Can I pass a component as a prop and keep it typed?
Yes—use React.ComponentType<T> or a function type. For example, { Icon: React.ComponentType<{ size: number }> } means Icon is a component that accepts a size prop. See Advanced: Generic Component Props with Constraints for deeper patterns.
What is the difference between React.FC and React.FunctionComponent?
No difference—React.FC is a shorthand alias for React.FunctionComponent. Both are identical in type signature.
How do I type a component that accepts no props?
Use an empty interface or omit the generic: const MyComponent: React.FC = () => <div /> or const MyComponent: React.FC<{}> = () => <div />. Both tell TypeScript the component accepts no props.