Conditional type based on value of other prop

Viewed 997

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?

2 Answers

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

Your collapsible prop is of boolean type, so it will either be false/true,

Can't you do something like this,

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

OR,

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

And then while implementation, you can easily check that onToggle is undefined or not. Because if something is optional and not provided then it's undefined by default in TS.

Related