Q:

Using instanceof to test for base class of a React component

To support nested navigation menu's, we're using React.cloneElement to add properties to child menu components (the menu components are custom components, based on react-bootstrap). To prevent that we're cloning all elements even though they are not child menu components, but regular content components, I want make the cloning conditional.
All menu components are sub classes of 'MenuBase' (which itself is a sub class of React.Component). In my code, I tried to test whether a child of a react component (reading this.props.children by use of the React.Children utility functions) is an instance of MenuBase.
Simplified code:
interface IMenuBaseProps {
  // menu related properties
}

abstract class MenuBase<P extends IMenuBaseProps, S> extends React.Component<P, S> {
  // constructor etc.
}

interface IGeneralMenuProps extends IMenuBaseProps {
  // additional properties
}

class GeneralMenu extends MenuBase<IGeneralMenuProps, {}> {
  public render(): JSX.Element {
    // do some magic
  }
}

Somewhere in the menu logic I want to do something like the following
React.Children.map(this.props.children, (child: React.ReactElement<any>): React.ReactElement<any> ==> {
  if (child instanceof MenuBase) {
    // return clone of child with additional properties
  } else {
    // return child
  }
}

However, this test never results in true and as a result a clone is never made.
In the Chrome developer tools I can see that:

child.type = function GeneralMenu(props)
child.type.prototype = MenuBase

Can somebody help me to clarify the following:

Why is instanceof not working
If I'm not able to use instance of the test for something in the inheritance chain of react components, what are my alternatives (I know I can test for the existence of one of the properties of IMenuBaseProps, but I don't really like that solution).

A:

Looking at the definition file, the ReactChildren.map is defined like this:
map<T>(children: ReactNode, fn: (child: ReactChild, index: number) => T): T[];

This ReactChild is then defined like this:
type ReactChild = ReactElement<any> | ReactText;

In your case it's probably ReactElement which is:
interface ReactElement<P> {
    type: string | ComponentClass<P> | SFC<P>;
    props: P;
    key?: Key;
}

Your MenuBase is the type, so it probably should be:
React.Children.map(this.props.children, (child: React.ReactElement<any>): React.ReactElement<any> ==> {
    if (child.type === MenuBase) {
        // return clone of child with additional properties
    } else {
        // return child
    }
}

It seems that the child.type is the class of the component and not the instance and so instead of doing child.type instanceof MenuBase you need to do child.type === MenuBase.  

Edit
After playing around with things I came up with this solution:
React.Children.map(this.props.children, (child: React.ReactElement<any>): React.ReactElement<any> ==> {
    if (MenuBase.isPrototypeOf(child.type)) {
        // return clone of child with additional properties
    } else {
        // return child
    }
}

If you'll want to check if the child is GeneralMenu then you'll need to do:
child.type.prototype === GeneralMenu.prototype

A:

The solution of @NitzanTomer did not seem to work under all circumstances. I was not able to find the cause of the difference in test results on his machine and my machine.
Finally I found the following solution:
public render(): JSX.Element {
    // Iterate over children and test for inheritance from ComponentBase
    let results: JSX.Element[] = React.Children.map(this.props.children, (child: React.ReactElement<any>, index: number): JSX.Element => {
        let isComponent: boolean = typeof child.type !== 'string' && React.Component.prototype.isPrototypeOf((child.type as any).prototype);
        let result: boolean = isComponent ? (child.type as any).prototype instanceof ComponentBase : false; // Not a component, then never a ComponentBase
        return <li>
                <div>Child nr. {index} is a React component: {isComponent ? "True" : "False"}</div>
                <div>And is a sub class of ComponentBase: {result ? "True" : "False"} { result !== this.props.expectedTestResult ? "(unexpected)" : ""}</div>
            </li>;
    })

    return (
        <ul>
            {results}
        </ul>
    )
}

In this solution, first a test is executed to check if the child is a React component. After that, 'instanceof' is used to determine whether the child component is a sub class of 'ComponentBase' (direct or indirect).
Because in TypeScript the 'type' property of React.Component does not have a 'prototype' property a cast to 'any' is necessary.

