Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Detecting React children array length in Typescript

I have a component that can accept React children as either a node or an array of nodes. I want to be able to detect if children is an array of nodes, but I am getting the following Typescript error:

TS2339: Property 'length' does not exist on type 'string | number | true | {} | ReactElement<any, string | ((props: any) => ReactElement<any, any> | null) | (new (props: any) => Component<any, any, any>)> | ... 47 more ... | (ReactNode[] & ReactPortal)'.   Property 'length' does not exist on type 'number'.

Is there a way in Typescript where I detect if children has length? Thanks.

import React from 'react';

interface Props {
  children: React.ReactNode | React.ReactNode[];
}

const SampleComponent: React.FC<Props> = ({ children }) => {
  if (children && children.length) {
    return children.map((child) => (
      <div>{child}</div>
    ));
  }

  return children;
};

export default SampleComponent;

enter image description here

like image 569
Jimmy Avatar asked Mar 25 '26 21:03

Jimmy


2 Answers

There is a React.Children API for dealing with the props.children (which is an opaque data structure).

Also, React.Children has methods like count, map etc.

if (React.Children.count(children)) {
  return React.Children.map(children, (child) => <div>{ ..todo.. }</div>)
}

It has TypeScript support too. So, you won't need to cast the types.

like image 98
Ajeet Shah Avatar answered Mar 27 '26 15:03

Ajeet Shah


[Update]

Please check out Ajeet Shah's response with using React.Children API.

[Original]

Cast children to React.ReactNode[] before checking length like this:

(children as React.ReactNode[]).length

You could also create a type predicate:

https://www.typescriptlang.org/docs/handbook/2/narrowing.html#using-type-predicates

like image 36
slaid3r Avatar answered Mar 27 '26 13:03

slaid3r