One of the changes made in the release of React v18 was to remove the built-in children?: React.ReactNode property from the React.FC type.

Up until this point, many developers were used to writing components that might have looked something like this:

type MyComponentProps = {
  style?: React.CSSProperties
}

const MyComponent : React.FC = ({ style, children }) => {
  return (<div style={style}>{children</div>)
}

We’re able to do this because the children property is built into React.FC.

Upgrading to React v18, developers will need to add explicitly children?: React.ReactNode to their type interface, for example:

type MyComponentProps = {
  style?: React.CSSProperties
  children?: React.ReactNode
}

const MyComponent : React.FC = ({ style, children }) => {
  return (<div style={style}>{children</div>)
}

Easy enough!

Unfortunately, some libraries have not made this upgrade and still use React.FC, which has the children property is included. In my case, @recurly/react-recurly had not been updated. This might not be a problem for everyone, but we needed to use yarn resolutions to ensure a consistent version react and react-dom are loaded throughout our monorepo.

{
  "resolutions": {
    "react": "^18.2.0",
    "react-dom": "^18.2.0",
    "@types/react": "^18.2.0",
    "@types/react-dom": "^18.2.0"
  }
}

Both components from Recurly’s library assume children, which gives the following errors:

import { Elements, RecurlyProvider } from '@recurly/react-recurly'

<RecurlyProvider publicKey={import.meta.env.VITE_RECURLY_KEY}>
  <Elements>
    <MyComponent />
  </Elements>
</RecurlyProvider>
Type '{ children: Element; publicKey: any; }' is not assignable to type 'IntrinsicAttributes & RecurlyOptions'.
  Property 'children' does not exist on type 'IntrinsicAttributes & RecurlyOptions'.ts(2322)
Type '{ children: Element; }' has no properties in common with type 'IntrinsicAttributes & ElementsProps'.ts(2559)

To work around this, we can declare the react module and force it to work like React v17.

import * as React from '@types/react';

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

Now libraries that haven’t been updated will work as they used to, even if they are referencing the old version of the types.