DEV Community

Cover image for TypeScript and React Children
Debbie O'Brien
Debbie O'Brien

Posted on • Updated on • Originally published at debbie.codes

TypeScript and React Children

What happens when we pass in children in React? Children is a special prop that allows us to pass in any type of element. It could be a number, a string, a boolean, an array of elements or even another component. So how can we check the types?

Of course we could define it as any which is basically the same as just not having type checking which defeats the whole purpose of using Typescript.

There are a couple of types we could choose from:

JSX.Element

Children must be a single JSX element. Doesn't allow multiple children, or strings etc.

type ButtonProps = {
  children: JSX.Element
}
const Button = ({ children }: ButtonProps) => <button>{children}</button>

export function Card() {
  return (
    <Button>
      <span>Click me</span>
    </Button>
  )
}
Enter fullscreen mode Exit fullscreen mode

JSX.Element[]

Allows multiple JSX elements but no strings, numbers etc

type ButtonProps = {
  children: JSX.Element[]
}
const Button = ({ children }: ButtonProps) => <button>{children}</button>

export default function Card() {
  return (
    <Button>
      <span>click me</span>
      <i>svg icon</i>
    </Button>
  )
}
Enter fullscreen mode Exit fullscreen mode

JSX.Element | JSX.Element[]

Allows single or multiple JSX elements but no strings, numbers etc

type ButtonProps = {
  children: JSX.Element | JSX.Element[]
}
const Button = ({ children }: ButtonProps) => <button>{children}</button>

export default function Card() {
  return (
    <Button>
      <span>click me</span>
    </Button>
  )
}
export default function Card2() {
  return (
    <Button>
      <span>click me</span>
      <i>svg icon</i>
    </Button>
  )
}
Enter fullscreen mode Exit fullscreen mode

React.ReactChild

Allows one React element, string or number

type ButtonProps = {
  children: React.ReactChild
}
const Button = ({ children }: ButtonProps) => <button>{children}</button>

export default function Card() {
  return <Button>click me</Button>
}
Enter fullscreen mode Exit fullscreen mode

React.ReactChild[]

Allows multiple React elements, strings or numbers

type ButtonProps = {
  children: React.ReactChild
}
const Button = ({ children }: ButtonProps) => <button>{children}</button>

export default function Card() {
  return (
    <Button>
      click me
      <i>svg icon</i>
    </Button>
  )
}
Enter fullscreen mode Exit fullscreen mode

React.ReactChild | React.ReactChild[]

Allows single or multiple React elements, strings or numbers

type ButtonProps = {
  children: React.ReactChild
}
const Button = ({ children }: ButtonProps) => <button>{children}</button>

export default function Card() {
  return <Button>click me</Button>
}

export default function Card2() {
  return (
    <Button>
      click me
      <i>svg icon</i>
    </Button>
  )
}
Enter fullscreen mode Exit fullscreen mode

React.ReactNode

Allows multiple children, strings, numbers, fragments, portals... We could use the above example but it is a little verbose and ReactNode covers a little more.

type ButtonProps = {
  children: React.ReactNode
}
const Button = ({ children }: ButtonProps) => <button>{children}</button>

export default function Card() {
  return (
    <Button>
      click me
      <i>svg icon</i>
    </Button>
  )
}
Enter fullscreen mode Exit fullscreen mode

Conclusion

And that's it, you now have no excuses for adding type checking for your children.

Useful Links

Discussion (9)

Collapse
kkomelin profile image
Konstantin Komelin

Hi Debbie,

Here is how I play with children:

import { FC, PropsWithChildren } from 'react';

type Props = {
  /* Other custom props */
}
const Component1:FC<PropsWithChildren<Props>> = ({children}) => {
  return (
    <>Component code</>
  )
}
Enter fullscreen mode Exit fullscreen mode
Collapse
anidel profile image
Aniello Del Sorbo

FC already accepts children, no need for PropsWithChildren.

If you don't want want children, you can use VFC.

Collapse
hellatan profile image
dale tan • Edited on

This is no longer true for FC with React 18. You must either use PropsWithChildren or explicitly add a children prop to your type definition.

Thread Thread
debs_obrien profile image
Debbie O'Brien Author

you're right. thanks for the comment.

Collapse
kkomelin profile image
Konstantin Komelin

Thank you Aniello! Good to know.

Thread Thread
debs_obrien profile image
Debbie O'Brien Author

thanks guys, will play around with it

Collapse
rerodrigues profile image
Renato Rodrigues • Edited on

Nice article! There is only a small mistake on the last example where it reads children: React.ReactChild instead of children: React.ReactNode

Collapse
debs_obrien profile image
Debbie O'Brien Author

ooops. thanks just corrected it. nice catch

Collapse
joset98 profile image
joset98

Thank you Debbie O'Brien, this post is great, i usually forget whats de diff between params type for children, this cheat post is Gold.