We are trying to migrate to react 18.
The children prop was removed from React.FunctionComponent (React.FC) so you have to declare it explicitly in your component properties.
But we want to keep the old React.FunctionComponent with children behavior. So, we are tryibg to override react types by creating a custom type definition file index.d.ts. This way we wont have to change 100s of components manually.
import * as React from '@types/react';
declare module 'react' {
//type PropsWithChildren<P> = P & { children?: ReactNode | undefined };
interface FunctionComponent<P = {}> {
(props: PropsWithChildren<P>, context?: any): ReactElement<any, any> | null;
}
}
We have components like below.
interface IProps {
age: number
}
const Demo: React.FunctionComponent<IProps> = ({
children,
age
}) => (
<>
{children}
{age}
</>
);
<Demo age={10}>Hi</Demo>
After overriding react types we are now getting following error in above Demo component.
Property 'children' does not exist on type 'IProps | PropsWithChildren<IProps>'
PropsWithChildren is defined in React 18 as below.
type PropsWithChildren<P> = P & { children?: ReactNode | undefined };
Below is the codesandbox link
https://codesandbox.io/s/quizzical-goodall-9d9s3j?file=/src/Demo.tsx
Ref :- React 18 TypeScript children FC
Any help?
2
Answers
General answer – you need to follow new rules of React 18, and you should change 100s files 🤷
The normal solution, for this case, will be to manually update component props interfaces to add
children
only where’s needed. But if it’s overkill for you, then add it to every component:React.FunctionComponent<
with
React.FunctionComponent<{children?: ReactNode | undefined } &
It’ll convert all your functional components to be like:
@alissa: it’s nicer to do
React.FunctionComponent<PropsWithChildren<IProps>>
then is something changes in the children type your code will be in syncReplace all
React.FunctionComponent<(w+)>
with
React.FunctionComponent<PropsWithChildren<$1>>
It seems that it’s impossible to override
React.FunctionComponent
in a mannar that will replace the props parameter type.The merging mechanism of a function interface, if you declare the same interface multiple times, is to add overloads of the function – create a more inclusive type. see docs
for example, if you declare interface
A
twice likeand then use interface
A
const foo: A = (a) => {}
the type of
a
will benumber | string
. and not justnumber
.Which makes sense, because someone might have already written some code assuming that A receives a parameter of type string.
Though I did manage to create a new type with the correct props
I think I would add a
FunctionComponentWithChildren
type and change my code to use it.