Search code examples
reactjstypescripttippyjs

Describe to typescript react component wrapper


How to describe wrapper around any children that tippy accepts that typescript will use correctly?

import Tippy, { TippyProps } from '@tippy.js/react'
import React from 'react'
import 'tippy.js/dist/tippy.css'

Tippy.defaultProps = {
  maxWidth: '500px',
}

export const Tooltip: Tooltip = ({ children, content, ...rest }) => {
  if (!children) return null
  if (!content) return children

  return (
    <Tippy content={content} {...rest}>
      {children}
    </Tippy>
  )
}

interface Tooltip {
  (props: MyProps): React.ForwardRefExoticComponent<TippyProps> | null | React.ReactNode
}

interface MyProps {
  content?: string | React.ReactNode
  children?: React.ReactNode
}

Used like this:

   <Tooltip content='Text'>
        <div>123</div>
   </Tooltip>

Typescript gives me error for children in return statement:

Type 'string | number | true | {} | ReactElement ReactElement Component)> | null) | (new (props: any) => Component)> | ReactNodeArray | ReactPortal' is not assignable to type 'ReactElement ReactElement Component)> | null) | (new (props: any) => Component)>'. Type 'string' is not assignable to type 'ReactElement ReactElement Component)> | null) | (new (props: any) => Component)>'.ts(2322) index.d.ts(6, 3): The expected type comes from property 'children' which is declared here on type 'IntrinsicAttributes & TippyProps'


Solution

  • The error points you right at the problem: you've declared children to be a ReactNode but ReactNode can be a string and Tippy (apparently) won't accept string children. Use ReactElement instead. When debugging typescript errors like this it is frequently helpful (at least until you get more used to reading them) to add whitespace formatting:

    Type 
    'string | number | true | {} | ReactElement ReactElement Component)> | null) 
    | (new (props: any) => Component)> 
    | ReactNodeArray 
    | ReactPortal' 
    is not assignable to type 
    'ReactElement ReactElement Component)> | null) 
    | (new (props: any) => Component)>'
    
    Type 'string' is not assignable to type 
    'ReactElement ReactElement Component)> | null) 
    | (new (props: any) => Component)>'
    
    ts(2322) index.d.ts(6, 3): The expected type comes from property 'children' 
    which is declared here on type 'IntrinsicAttributes & TippyProps'