I have the component that renders the content of the tab. It simply detects if children is only child and if not it wraps them in div. It also can (optionally) apply prop with styles by cloning the child. I wrote this component many months ago, then I updated some libraries and TypeScript. Today I am watching its code and I see errors.
The component
import * as React from 'react';
export interface PageTabContentShape {
title: string;
pageTabName?: string;
withContainer?: boolean;
containerStyle?: React.CSSProperties;
labelTestid?: string;
children: React.ReactElement;
}
export const PageTabContent: React.ComponentType<PageTabContentShape> = (props) => {
let child = React.Children.only(props.children);
if (props.withContainer) {
return (
<div style={props.containerStyle}>
{child}
</div>
);
}
// pass styles to only child when there is no wrapper
if (props.containerStyle && React.isValidElement<{ containerStyle }>(child)) {
child = React.cloneElement(child, { containerStyle: props.containerStyle });
}
if (null != child) {
return child;
}
return null;
};
Errors:
Argument type ReactElement<{containerStyle}> is not assignable to parameter
type DetailedReactHTMLElement<HTMLAttributes<HTMLElement>, HTMLElement>
and
Argument type {containerStyle: React.CSSProperties} is not assignable to parameter
type HTMLAttributes<HTMLElement> | undefined
Place of the errors:
I tried different approaches, adding null checks and returning early with null, adding type assertions as ReactNode or as ReactElement. But I can't make TypeScipt choose another definition of the cloneElement method which I see in index.d.ts of @types/React
Question
How can I properly declare this component to make TypeScript errors vanish? If it is possible I would like to do it without types assertion. If it is possible I need to do it without any NPM updates (might consider minor update).
Packages in use:
- "@types/react": "16.9.1",
- "react": "16.9.0",
- "typescript": "3.8.2",

