15 votes

Comment remplacer correctement le type any lorsque l'on retourne des enfants ou une carte d'enfants dans un tableau ?

J'ai un composant React function qui vérifie si children est un tableau. Si ce n'est pas un tableau, il le renvoie. Sinon, il mappe sur les enfants et renvoie du JSX.

import React from 'react'

interface Props {
  children: React.ReactNode
}

const LineBreak: React.FC<Props> = ({ children }): any => {
  if (!Array.isArray(children)) return children
  return (
    <>
      {children.map((child, i, arr) => {
        if (i + 1 === arr.length) return child
        return <>{child}<br /></>
      })}
    </>
  )
}

export default LineBreak

Ce que je voudrais faire, c'est remplacer le any sur la ligne 7. Je pense logiquement que le changer en React.ReactNode suffirait, mais cela déclenche l'erreur de type :

Type '({ children }: PropsWithChildren<Props>) => ReactNode' is not assignable to type 'FC<Props>'.
  Type 'ReactNode' is not assignable to type 'ReactElement<any, any>'.
    Type 'string' is not assignable to type 'ReactElement<any, any>'.ts(2322)

J'aurais vraiment besoin de quelques conseils sur la façon de lire correctement ces messages d'erreur.

J'ai également essayé de contourner ce message d'erreur en changeant le type de retour en string|React.ReactNode et je m'attendais à la même erreur parce que, d'après mes connaissances limitées en écriture de type React.ReactNode inclut le type string.

17voto

amaster507 Points 1009

J'ai pu résoudre ce problème avec deux méthodes différentes.

  1. Supprimez le type React.FC de la fonction.

    import React from 'react'

    interface Props { children: React.ReactNode }

    const LineBreak = ({children}: Props): React.ReactNode => { if (!Array.isArray(children)) return children return ( <> {children.map((child, i, arr) => { if (i + 1 === arr.length) return child return <>{child}<br /></> })} </> ) }

    export default LineBreak

  2. Enveloppe le retour enfant unique à l'intérieur d'un Fragment.

    import React from 'react'

    interface Props { children: React.ReactNode }

    const LineBreak: React.FC<Props> = ({children}): JSX.Element => { if (!Array.isArray(children)) return <>{children}</> return ( <> {children.map((child, i, arr) => { if (i + 1 === arr.length) return child return <>{child}<br /></> })} </> ) }

    export default LineBreak

D'après ce que je comprends maintenant, un React.FC ne peut être qu'un type de retour de JSX.Element ou équivalent. Alors que les enfants peuvent être de type string, boolean, {} ce qui n'est pas conforme au type JSX.Element. Donc, si je veux contrôler le type de retour, je dois supprimer le React.FC, ou si je veux utiliser le React.FC, je dois envelopper le retour des enfants à l'intérieur d'un fragment afin qu'il renvoie correctement les différents types d'enfants comme un type JSX.Element valide.

4voto

Moshe Sommers Points 50

Les solutions de @amaster sont bonnes. J'ajoute juste ma compréhension des messages d'erreur

Je pense que c'est ce que l'erreur signifie

Le message d'erreur indique que le type de retour attendu pour l'option FC<Props> est ReactElement<any, any>

Alors Type '({ children }: PropsWithChildren<Props>) => ReactNode' is not assignable to type 'FC<Props>'. Signifie que quelque chose avec un type de retour de ReactNode ne correspond pas au type de retour attendu de ReactNode. FC<Props>

Et Type 'ReactNode' is not assignable to type 'ReactElement<any, any>'. Cela signifie que vous essayez d'assigner ReactNode comme type de retour au lieu du type attendu. ReactElement<any, any>

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X