返回子项或子项映射(如果数组)时如何正确替换类型 any

ama*_*ter 24 javascript types typescript reactjs

我有一个 React 函数组件来检查 Children 是否是一个数组。如果它不是数组,则返回它。否则,它会映射子级并返回一些 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
Run Code Online (Sandbox Code Playgroud)

我想做的是替换any第 7 行。从逻辑上讲,我认为将其更改为React.ReactNode就足够了,但这会引发类型错误:

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)
Run Code Online (Sandbox Code Playgroud)

我真的可以使用一些关于如何正确阅读这些错误消息的指示。

我还尝试通过将返回类型更改为来绕过此错误消息,string|React.ReactNode并预期会出现相同的错误,因为根据我有限的打字稿知识,React.ReactNode 包含类型字符串。

ama*_*ter 29

我能够用两种不同的方法解决这个问题。

  1. 从函数中删除 React.FC 类型。
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
Run Code Online (Sandbox Code Playgroud)
  1. 将单个子返回包裹在 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
Run Code Online (Sandbox Code Playgroud)

据我现在的了解,React.FC 只能是 JSX.Element 或等效的返回类型。而子项可能是字符串、布尔值、{} 类型,不符合 JSX.Element 类型。因此,如果我想控制返回类型,那么我必须删除 React.FC,或者如果我想使用 React.FC,那么我需要将子级的返回包装在片段内,以便它正确返回各种子类型作为有效的 JSX.Element 类型。


Mos*_*ers 7

@amaster 的解决方案很好。只是添加我对错误消息的理解

我认为这就是错误的含义

该错误表明预期的返回类型FC<Props>ReactElement<any, any>

所以 Type '({ children }: PropsWithChildren<Props>) => ReactNode' is not assignable to type 'FC<Props>'. 意味着返回类型为 ReactNode 的东西与预期返回类型不匹配FC<Props>

Type 'ReactNode' is not assignable to type 'ReactElement<any, any>'.表示您正在尝试将 ReactNode 指定为返回类型而不是预期的ReactElement<any, any>


use*_*488 5

修复方法是ReactElement返回FC. 但是您也必须进行设置children

import React from 'react'

interface Props {
  children: React.ReactElement
}

const LineBreak: React.FC<Props> = ({ children }): React.ReactElement => {
  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
Run Code Online (Sandbox Code Playgroud)