Search code examples
reactjstypescripttogglereact-propsreact-typescript

Conditional type based on value of other prop


In my project I have a component which takes two props:

collapsible,
onToggle

I struggle to create a type for these props in TypeScript. The problem is that when the collapsible is true I want the onToggle function to be a (): void but if collapsible is false I want the onToggle to be undefined.

I tried something like this:

type Props = {
  collapsible: boolean;
  onToggle: collapsible ? () => void : undefined;
}

But obviously it does not work, since the collapsible is undefined when defining onToggle type. How to deal with that? Is that even possible to have types depend on values?


Solution

  • You can use a discriminated union (discriminated on collapsible):

    type Props = {
        common?: string
    } & ({
        collapsible?: false;
        onToggle?: never;
    } | {
        collapsible: true;
        onToggle: () => void
        })
    
    function Test(p: Props) {
        return <></>
    }
    
    function Usage() {
        return <>
            <Test /> {/* Ok */}
            <Test collapsible={false} /> {/* Ok */}
            <Test collapsible={true} /> {/* Err, as expected */}
            <Test collapsible={true} onToggle={() => { }} /> {/* ok */}
        </>
    }
    
    

    Playground Link