javascript - Cómo reemplazar correctamente el tipo any al devolver hijos o un mapa de hijos si es un arreglo
Tengo un componente funcional de React que verifica si los children son un array. Si no es un array, entonces lo devuelve. De lo contrario, itera sobre los children y devuelve algo de 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
Lo que me gustaría hacer es reemplazar el any en la línea 7. Lógicamente, pienso que cambiarlo a React.ReactNode sería suficiente, pero eso genera el error de tipo:
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)
Realmente podría usar algunos consejos sobre cómo leer correctamente estos mensajes de error.
También intenté evitar este mensaje de error cambiando el tipo de retorno a string|React.ReactNode y esperaba el mismo error porque, según mi conocimiento limitado de TypeScript, React.ReactNode incluye el tipo string.
Respuesta #1
Pude resolver esto con dos métodos diferentes.
- Elimina el tipo React.FC de la función.
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
- Envuelve el único hijo devuelto dentro de 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
Por lo que entiendo ahora, un React.FC solo puede ser un tipo de retorno de JSX.Element o equivalente. Aunque los children pueden ser de tipo string, boolean, {}, eso no se ajusta al tipo JSX.Element. Así que si quiero controlar el tipo de retorno, entonces tengo que eliminar el React.FC, o si quiero usar el React.FC, entonces necesito envolver el retorno de los children dentro de un fragmento para que devuelva correctamente los diversos tipos de children como un tipo válido de JSX.Element.
Respuesta #2
Las soluciones de @amaster son buenas. Solo agregando mi comprensión de los mensajes de error
Creo que esto es lo que significa el error
El error dice que el tipo de retorno esperado para FC<Props> es ReactElement<any, any>
Entonces Type '({ children }: PropsWithChildren<Props>) => ReactNode' no es asignable al tipo FC<Props>. Significa que algo con un tipo de retorno ReactNode no coincide con el tipo de retorno esperado de FC<Props>
Y Type 'ReactNode' is not assignable to type 'ReactElement<any, any>'. Está diciendo que estás intentando asignar ReactNode como tipo de retorno en lugar del esperado ReactElement<any, any>
