How to type compound components with ref forwarding

Viewed 889

I'm trying to customize Chakra-ui tab components. According to their docs it must be wrapped in React.forwardRef since they use cloneElement to pass state internally. But then TS complains:

[tsserver 2559] [E] Type '{ children: string; }' has no properties in common with type 'IntrinsicAttributes & { isSelected?: boolean | undefined; } & RefAttributes<HTMLElement>'.

Is it possible to add types to CoolTab component so that it will still work with their api?

const CoolTab = React.forwardRef<HTMLElement, { isSelected?: boolean }>((props, ref) => {
  return (
    <Tab ref={ref} isSelected={props.isSelected} {...props}>
      {props.isSelected ? '' : ''}
      {props.children}
    </Tab>
  )
})

CoolTab.displayName = 'CoolTab'

const Module = () => {
  return (
    <CenterLayout>
      <Card>
        <Tabs>
          <TabList>
            <CoolTab>General</CoolTab>
            <Tab>Notifications</Tab>
          </TabList>

          <TabPanels>
            <TabPanel>
              <p>one!</p>
            </TabPanel>
            <TabPanel>
              <p>two!</p>
            </TabPanel>
          </TabPanels>
        </Tabs>
      </Card>
    </CenterLayout>
  )
}

https://chakra-ui.com/tabs#creating-custom-tab-components

1 Answers

I ended up, typing my component like this:

const BottomSheet: React.ForwardRefExoticComponent<BottomSheetProps> & {Header?: React.FC }

BottomSheet.Header = ({ children }) => { return <h1>Header</h1> }

Still this has the downside of making the Header property optional

Related