Comment typer la prop children de React.FC dans React 18 avec Typescript ?

author
Andréas Hanss · Aug 10, 2022
dev | 2 min
Article image

En utilisant le nouveau type React.FC sur votre projet existant, vous pouvez rencontrer l'erreur suivante :

Property ‘children’ does not exist on type <YourCustomTypeProps>

Cela parce que la signature du type à changé dans les versions récentes de React !

Pourquoi la signature de React.FC à changé ?

La propriété children a été retirée du type React.FunctionComponent (React.FC) on va donc devoir la déclarer explicitement dans nos propre propriétés.

TLDR; Cela permet de prévenir les bugs comme celui-ci :

1
const ComponentWithNoChildren: React.FC = () => <>Hello</>;
2
3
<ComponentWithNoChildren>
4
// Cela ne sera pas utilisé car le composant parent n'utilise pas la prop children.
5
<UnusedChildrenSinceComponentHasNoChildren />
6
</ComponentWithNoChildren>

Ainsi, vous pouvez être certain que le composant que vous utilisez prend en charge les enfants, et améliorer votre base de code/qualité.

Comment utiliser React.FC et la prop children dans React 18+ ?

Avant

Dans les versions précédentes la propriété children était déjà définie en tant que propriété optionnelle dans le type React.FC.

1
import * as React from 'react';
2
3
type Props = {};
4
5
const Component: React.FC<Props> = ({children}) => {...}

Après

Dans les versions récentes, cela à été supprimé. Maintenant il faut désormais spécifier explicitement la propriété selon notre besoin. Elle peut être requise ou optionnelle selon les besoins de notre logique métier.

1
import * as React from 'react';
2
3
type Props = { children?: React.ReactNode};
4
5
const Component: React.FC<Props> = ({children}) => {...}

Que faire si je souhaite conserver l'ancien comportement de React.FC et de la propriété children ?

Il est possible de surcharger les types de React en créant un fichier de définition personnalisé. Cela peut être un fichier de définition global que l'on utilise déjà dans le projet ou alors il est possible d'en créer un nouveau avec un nom arbitraire comme react.d.ts tant qu'il se trouve dans le périmètre de compilation TypeScript.

La définition suivante rétabliera le comportement équivalent aux type de @types/react version 17.

1
import * as React from '@types/react';
2
3
declare module 'react' {
4
interface FunctionComponent<P = {}> {
5
(props: PropsWithChildren<P>, context?: any): ReactElement<any, any> | null;
6
}
7
}

Il ne reste plus qu'à profiter de notre forte définition de type ;)