TypeScript Definition Changes in React 18: Resolving the 'Property 'children' does not exist on type 'ReactNode'' Error

Dec 07, 2025 · Programming · 9 views · 7.8

Keywords: React 18 | TypeScript | children property | type definitions | PropsWithChildren

Abstract: This article delves into the common TypeScript error 'Property 'children' does not exist on type 'ReactNode'' encountered in React 18 and above. By analyzing significant changes in React 18's type definitions, particularly the removal of implicit children properties in the FunctionalComponent interface, it offers multiple solutions, including explicit definition of children properties, use of the PropsWithChildren type, and comparisons with React 17 and earlier versions. Based on high-scoring Stack Overflow answers, the content combines code examples and official documentation to help developers understand and adapt to this change, ensuring type safety while enhancing code maintainability.

Problem Background and Error Analysis

In React development with TypeScript, many developers are accustomed to using the ReactNode type to define the children property of components. However, after upgrading to React 18, they may encounter the following TypeScript error: Property 'children' does not exist on type 'ReactNode'. This often occurs in code like:

export const PageViewTracker = ({ children }: ReactNode): ReactElement => {
    usePageView();
    return children;
};

The core issue is that ReactNode is a type representing React nodes (such as elements, strings, numbers), not an object type containing a children property. Prior to React 18, the FunctionalComponent (or FC) interface implicitly included the children property, but this design changed in React 18.

Type Definition Changes in React 18

React 18 introduced significant adjustments to TypeScript type definitions. In @types/react version 18.0.0 and above, the FunctionalComponent interface is defined as:

interface FunctionComponent<P = {}> {
    (props: P, context?: any): ReactElement<any, any> | null;
    propTypes?: WeakValidationMap<P> | undefined;
    contextTypes?: ValidationMap<any> | undefined;
    defaultProps?: Partial<P> | undefined;
    displayName?: string | undefined;
}

The key change is that the props parameter type no longer automatically includes PropsWithChildren. This means the children property is no longer implicitly added to the props of functional components. This change aims to improve type safety by preventing misuse in components that don't require children, and to simplify type inference. According to official release notes, this adjustment stems from community feedback and type definition optimizations (refer to relevant GitHub commits).

Solutions

For React 18 and above, developers need to handle the children property explicitly. Here are several recommended approaches:

Method 1: Explicitly Define the children Property

Include the children property explicitly in the component props interface, with the type React.ReactNode. For example:

interface Props {
  children: React.ReactNode;
}

export const PageViewTracker: React.FC<Props> = ({ children }) => {
    usePageView();
    return children;
};

This method ensures type safety and clearly expresses the expected structure of the component.

Method 2: Use the PropsWithChildren Type

The React library still provides the PropsWithChildren type, which can be used for optional or required children properties. Its definition is:

type PropsWithChildren<P = unknown> = P & { children?: ReactNode | undefined };

Application example:

import { PropsWithChildren } from 'react';

interface Props {
  foo: string;
}

export const PageViewTracker: React.FC<PropsWithChildren<Props>> = ({ children, foo }) => {
    usePageView();
    return children;
};

This allows flexible handling of children while maintaining other props types.

Comparison with React 17 and Earlier Versions

In React 17 and earlier versions, the FunctionalComponent interface default included the children property, defined as:

interface FunctionComponent<P = {}> {
    (props: PropsWithChildren<P>, context?: any): ReactElement | null;
    propTypes?: WeakValidationMap<P>;
    contextTypes?: ValidationMap<any>;
    defaultProps?: Partial<P>;
    displayName?: string;
}

Here, the PropsWithChildren type is P & { children?: ReactNode };. Thus, developers could directly use React.FC without explicitly defining children, for example:

export const PageViewTracker: React.FC = ({ children }) => {
    usePageView();
    return children;
};

This implicit behavior was removed in React 18 to promote more precise type checking.

Practical Recommendations and Migration Guide

When upgrading to React 18, it is advisable to follow these steps:

  1. Review existing components: Identify all components using React.FC or similar types, ensuring the children property is handled correctly.
  2. Update type definitions: Based on component needs, choose to explicitly define children or use PropsWithChildren.
  3. Test validation: Run the TypeScript compiler and unit tests to ensure no type errors or behavioral changes.
  4. Refer to official documentation: Consult the React 18 upgrade guide and related TypeScript definition release notes for the latest information.
Additionally, avoid using the any type as a temporary solution, as it weakens type safety. By using explicit types, code readability and maintainability can be enhanced.

Conclusion

The changes in TypeScript type definitions in React 18, particularly the shift from implicit to explicit inclusion of the children property in the FunctionalComponent interface, reflect ongoing improvements in type safety and developer experience. By understanding this change and adopting appropriate solutions, such as explicitly defining the children property or leveraging the PropsWithChildren type, developers can smoothly migrate and build more robust React applications. This adjustment encourages clearer component interface design, aligning with best practices in modern front-end development.

Copyright Notice: All rights in this article are reserved by the operators of DevGex. Reasonable sharing and citation are welcome; any reproduction, excerpting, or re-publication without prior permission is prohibited.