Polymorphism React/typescript : how to tell typescipt that the caller of a component with generic children do not need to specify the child props

22 views Asked by At

So I want to make some reusable component that accepts different kind of react components (ReactNode) as children that have common props

type ChildrenProps  <C extends React.ReactNode> =  {
    refreshResult?: boolean,
    SetRefreshResult?:(flag: boolean) => void,
    SetDisplayResult?: (flag: boolean) => void
}

and specific props. As there is a generic behavior whatever the kind of children I wanted to set the common props to the same value whatever the children. For that I intended to do the following, render a button and a ReactNode (children) within a component Section. Some props of the children should be set within Section and not by the parent of Section as these props should by assigned to the same value as the behavior should be the same for all kind of children.

Section.tsx

type ChildrenProps  <C extends React.ReactNode> =  {
    refreshResult?: boolean,
    SetRefreshResult?:(flag: boolean) => void,
    SetDisplayResult?: (flag: boolean) => void
}

type Props <C extends React.ReactNode> =
React.PropsWithChildren<ChildrenProps<C>> &
SectionProps

interface SectionProps
{
    children: ChildrenProps<React.ReactNode>,
    button_props:Omit<Button, 'onClick'>

}


export default function Section({children,button_props}:Props<React.ReactNode>)
{

    const [DisplayResult,SetDisplayResult] =  useState(false)

    const [RefreshResult,SetRefreshResult] =  useState(false)

    const handleResult = () => {
        SetDisplayResult(true)
        SetRefreshResult(true)
    }

    children.SetDisplayResult = SetDisplayResult
    children.SetRefreshResult = SetRefreshResult
    children.refreshResult = RefreshResult


    return ( 
        <>
            <Button onClick={handleResult}
             {...button_props}/>
                {children} 
        </>
        )   

}

Now when I call the Section component, I need to specify the props of its children, so I got a typescript error.

typescript error: Type '{}' is missing the following properties from type 'Text': refreshQuote, SetRefreshQuote, SetDisplayQuotets(2739)*/

You can see below

GetCurrentText.tsx

import Section
import Text

interface TextProps
{
    disable:boolean
}

export default function GetCurrentText({disable}:TextProps)
{
    const button_props = 
    {
        disable : disable,
        text :"Read latest quote of last author on Blockchain"

    }



    return(
        <Section button_props={button_props}>
            <Text/> /* !!!!!!!!! typescript error: Type '{}' is missing the following properties
            from type   'Text': refreshQuote, SetRefreshQuote, SetDisplayQuotets(2739)*/
        </Section>
    )
}

I can of course specify dummy values for the props but that would be a dirty solution. In this case I do not want to specify the props of the children of Section since there are set within Section see above.

You can see the interface for Text component below

Text.tsx

    interface GetCurrentTextProps{
        refreshQuote:boolean,
        SetRefreshQuote: (flag: boolean) => void, 
        SetDisplayQuote: (flag: boolean) => void
    }


 export default function  GetCurrentText({refreshQuote,SetRefreshQuote,SetDisplayQuote}:GetCurrentTextProps)
    {
               ....
     }

How can I indicate to typescript that a component that render Section and children do not need to specify the props for the children since there are set within Section?

I tried to make the ChildrenProps optional so that the caller of Section do not need to set the props of its children but it did not helped since the component used as children requires those props. I could also go on the specific component here <Text/> and make the props optional but it would not make sense to modify the interface of a component only to make it reusable without any functional needs behind the modification.

0

There are 0 answers