Since React 18 and @types/react v18, React.FC no longer includes children in the props type by default. You must explicitly declare children in your props interface or use PropsWithChildren to accept child elements.
This TypeScript error occurs when using React.FC (or React.FunctionComponent) with components that accept children, but the children prop is not explicitly declared in the props type. Starting with @types/react v18 (corresponding to React 18), the FC type was changed to remove the implicit children prop that was previously included by default. This change was intentional and improves type safety by preventing components from accidentally accepting children they don't use. Previously, all FC components implicitly had a children prop even if they never rendered children, which could lead to silent bugs where children were passed but ignored. The error typically manifests when TypeScript reports that 'children' does not exist on the props type, or when trying to use props.children in a component typed with React.FC without explicitly including children in the props interface.
The most straightforward solution is to explicitly declare children in your props type:
import React, { ReactNode } from 'react';
interface MyComponentProps {
title: string;
children: ReactNode;
}
const MyComponent: React.FC<MyComponentProps> = ({ title, children }) => {
return (
<div>
<h1>{title}</h1>
{children}
</div>
);
};Use ReactNode as the type for children since it accepts all valid React child types (elements, strings, numbers, fragments, portals, etc.).
React provides a PropsWithChildren utility type that wraps your props and adds children:
import React, { PropsWithChildren } from 'react';
interface MyComponentProps {
title: string;
}
const MyComponent: React.FC<PropsWithChildren<MyComponentProps>> = ({
title,
children
}) => {
return (
<div>
<h1>{title}</h1>
{children}
</div>
);
};This approach keeps your props interface clean while explicitly declaring that children are accepted.
Many developers now prefer to avoid React.FC altogether and use regular function syntax:
import React, { ReactNode } from 'react';
interface MyComponentProps {
title: string;
children: ReactNode;
}
function MyComponent({ title, children }: MyComponentProps) {
return (
<div>
<h1>{title}</h1>
{children}
</div>
);
}
// Or with arrow function
const MyComponent = ({ title, children }: MyComponentProps) => {
return (
<div>
<h1>{title}</h1>
{children}
</div>
);
};This approach is more explicit and is the pattern recommended by many in the React community, including the React team.
If your component should NOT accept children, simply don't include children in the props type. React.FC will correctly prevent children from being passed:
import React from 'react';
interface ButtonProps {
label: string;
onClick: () => void;
}
const Button: React.FC<ButtonProps> = ({ label, onClick }) => {
return <button onClick={onClick}>{label}</button>;
};
// TypeScript will error if you try:
// <Button label="Click me" onClick={handleClick}>Invalid children</Button>This is actually one of the benefits of the changeโit prevents accidentally passing children to components that don't use them.
Why the change was made:
The removal of implicit children from React.FC was a deliberate decision to improve type safety. Previously, every FC component accepted children even if it never used them, which could lead to confusing behavior where children were passed but silently ignored. By making children explicit, TypeScript can now catch these mismatches at compile time.
TypeScript 5.1+ improvements:
As of TypeScript 5.1, React.FC has been further improved to accept more return types (string, number, undefined) without errors, making it more aligned with standard function components. The team at TypeScript and React now consider React.FC "fine" to use, whereas it was previously discouraged due to various limitations.
Migration strategy for large codebases:
If you're upgrading a large codebase from React 17 to 18, you can create a temporary alias to ease migration:
// types/react-legacy.ts
import { FC, PropsWithChildren } from 'react';
export type LegacyFC<P = {}> = FC<PropsWithChildren<P>>;Then gradually migrate components from LegacyFC to properly typed FC components, making children explicit only where needed.
Optional children:
If children should be optional, use:
interface Props {
children?: ReactNode;
}This allows the component to work with or without children, which is useful for wrapper components that have default content.
Warning: You provided a `selected` prop to a form field without an `onChange` handler
You provided a 'selected' prop without an onChange handler
Failed to load source map from suspense chunk
How to fix "Failed to load source map from suspense chunk" in React
Prop spreading could cause security issues
Prop spreading could cause security issues
React Hook useCallback has a missing dependency: 'variable'. Either include it or remove the dependency array react-hooks/exhaustive-deps
React Hook useCallback has a missing dependency
Cannot use private fields in class components without TS support
Cannot use private fields in class components without TS support