How to Properly Define Props for Functional Components Using React.FC in TypeScript

Annotate your functional component with the generic type React.FC<Props> (or React.FunctionComponent<Props>) to automatically receive typed children and enforce that your function returns a valid React.ReactElement or null.

When building applications with the facebook/react codebase, properly typing functional components prevents runtime errors and improves developer experience through autocomplete. The React.FC generic type alias provides a standardized way to declare component contracts in TypeScript without manually adding the children prop.

Understanding the React.FC Generic Type

React.FC<P> is a TypeScript alias for React.FunctionComponent<P>. It represents a function component whose props are described by the generic argument P. According to the type definitions in the React repository, this generic automatically injects an optional children?: ReactNode field into your props and constrains the return type to something assignable to React.ReactElement or null.

Key characteristics include:

  • Generic typing: Accepts a single type argument describing your props interface.
  • Implicit children: Automatically adds children?: React.ReactNode unless overridden.
  • Return type safety: Ensures the component returns a valid React element.

Step-by-Step: Defining Props with React.FC

Declaring the Props Interface

First, define an interface or type alias describing every prop your component expects. Exclude children from this definition, as React.FC will add it automatically.

import React from 'react';

interface GreetingProps {
  /** Text to display */
  message: string;
  /** Optional CSS class name */
  className?: string;
  // Note: children is NOT declared here; React.FC adds it automatically
}

Applying the Type Annotation

Assign React.FC<YourPropsType> as the type annotation for your component constant or function. This enables TypeScript to check prop usage within the component body.

const Greeting: React.FC<GreetingProps> = ({message, className, children}) => (
  <div className={className}>
    <p>{message}</p>
    {children /* typed as ReactNode automatically */}
  </div>
);

export default Greeting;

Automatic Children Prop Handling

One primary advantage of React.FC is the automatic inclusion of the children prop. When you use React.FC<Props>, TypeScript merges your custom props with children?: React.ReactNode, allowing child elements to be passed without explicit typing in your interface.

This behavior is implemented in React's type definitions and used throughout the codebase. For example, in compiler/packages/snap/src/sprout/shared-runtime.ts, the internal createHookWrapper utility leverages FunctionComponent<TProps> to ensure wrapped components maintain standard React component signatures:

import React, {FunctionComponent} from 'react';

export function createHookWrapper<TProps, TRet>(
  useMaybeHook: (props: TProps) => TRet,
): FunctionComponent<TProps> {
  return function Component(props: TProps): React.ReactElement {
    const result = useMaybeHook(props);
    // Stringify helper used here...
    return <div>{result}</div>;
  };
}

This pattern demonstrates how FunctionComponent<TProps> (the long-form alias for React.FC) enforces that the returned function accepts the specified props plus optional children.

When to Use Explicit Function Types Instead

If you need a component that must not receive children, or if you prefer explicit control over the function signature, avoid React.FC and type the function directly:

import React from 'react';

type ButtonProps = {
  label: string;
  onClick: () => void;
};

const Button = (props: ButtonProps): React.ReactElement => (
  <button onClick={props.onClick}>{props.label}</button>
);

Direct function typing is preferred when:

  • You want to strictly forbid children (children won't be in scope).
  • You need to define generic components with complex type parameters.
  • You want to avoid the implicit children prop for API clarity.

Complete TypeScript Examples

Basic Functional Component with React.FC

import React from 'react';

interface CardProps {
  title: string;
  content: React.ReactNode;
}

const Card: React.FC<CardProps> = ({title, content, children}) => (
  <section>
    <h2>{title}</h2>
    <div>{content}</div>
    {children}
  </section>
);

Component Excluding Children

import React from 'react';

type AvatarProps = {
  src: string;
  alt: string;
};

const Avatar = (props: AvatarProps): React.ReactElement => (
  <img src={props.src} alt={props.alt} />
);

Higher-Order Component Using React.FC

Following the pattern found in compiler/packages/snap/src/sprout/shared-runtime.ts, you can use React.FC in HOCs:

import React from 'react';

type WithLabelProps = {
  label: string;
};

function withLabel<P>(Component: React.FC<P>) {
  const Wrapped: React.FC<P & WithLabelProps> = ({label, ...rest}) => (
    <>
      <div>{label}</div>
      <Component {...(rest as P)} />
    </>
  );
  return Wrapped;
}

Summary

  • Use React.FC<Props> when you want automatic children typing and a concise component definition.
  • Declare props interfaces without children, as React.FC injects children?: ReactNode automatically.
  • Reference FunctionComponent in generic utilities, as demonstrated in compiler/packages/snap/src/sprout/shared-runtime.ts.
  • Avoid React.FC and use explicit function types (props: Props) => React.ReactElement when you need to exclude children or require stricter type control.

Frequently Asked Questions

What is the difference between React.FC and React.FunctionComponent?

There is no functional difference. React.FC is a type alias for React.FunctionComponent. Both accept a single generic argument describing your props type and provide identical typing for the children prop and return value. The React source code uses FunctionComponent in internal helpers like createHookWrapper for clarity, but React.FC is the standard shorthand used in application code.

Does React.FC automatically include the children prop?

Yes. React.FC<Props> automatically intersects your props type with { children?: React.ReactNode }. This means you do not need to declare children in your props interface, and TypeScript will correctly type the children parameter within your component function. If you need to change the children type (e.g., to require a single child), you must extend the interface manually or use direct function typing instead.

When should I avoid using React.FC?

Avoid React.FC when you need to strictly forbid children from being passed to your component, or when building generic components where React.FC's fixed generic structure interferes with complex type inference. In these cases, use direct function typing: const Component = (props: Props): JSX.Element => .... This approach gives you explicit control over the signature without the automatic children field.

How are React.FC types tested in the React repository?

The React team maintains test-only type definitions in files like packages/react/src/__tests__/testDefinitions/React.d.ts and ReactInternalAct.d.ts. These files contain minimal type scaffolding that validates the core type surface, including Component and createElement typings, ensuring that FunctionComponent and related generics behave correctly across different TypeScript versions.

Have a question about this repo?

These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →