Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Conditional type for react props with default optional value

I want to have conditional props types

When i try to pass a default value to my optional prop, which is inside the conditional type, the types break

export type ChatBase = {
  id: string;
  title: string;
}

type ChatCardProps = { title: string; } &
  (
    | {
        chat: ChatBase & { createdBy: { displayName: string } };
        hideCreator?: false;
      }
    | {
        chat: ChatBase;
        hideCreator: true;
      }
  );

const Chat = ({ title, chat, hideCreator = false }: ChatCardProps) => {
  return (
    <div>
      <p>{title}</p>
      {!hideCreator && <p>{chat.createdBy.displayName}</p>}
      {/*                           ^? createdBy?: { displayName: string; } | undefined */}
    </div>
  )
}

const Chat2 = ({ title, chat, hideCreator }: ChatCardProps) => {
  return (
    <div>
      <p>{title}</p>
      {!hideCreator && <p>{chat.createdBy.displayName}</p>}
      {/*                          ^? createdBy?: { displayName: string; } */}
    </div>
  )
}

Why when I pass an default value the logic breaks?

CodeSandbox: https://codesandbox.io/s/nameless-browser-hgshpz?file=/src/App.tsx:349-350

like image 723
Stavros Avatar asked Nov 27 '25 20:11

Stavros


1 Answers

You can do it using type casting here is the sandbox link where I did some updating inside your code-sandbox snippet

Apart from that you can do it using generics here is the reference code snippet for that but it will change whole code and more efforts will be required in that case

 type ChatType<HasDisplayName extends boolean> = HasDisplayName extends true
  ? ChatBaseWithdisplayName
  : ChatBaseWithoutDisplayName;

// Usage with a condition
const hasDisplayName = true; // Example condition

const chat: ChatType<typeof hasDisplayName> = {
  title: "Chat Title",
  // ... other properties based on the selected type
};

// Alternatively, without a condition (always uses ChatBaseWithdisplayName)
const chatAlwaysDisplayName: ChatType<true> = {
  title: "Chat Title",
  // ... other properties based on ChatBaseWithdisplayName
};

const chatNoDisplayName: ChatType<false> = {
  title: "Chat Title",
  // ... other properties based on ChatBaseWithoutDisplayName
};
like image 192
Prashant Shah Avatar answered Nov 30 '25 10:11

Prashant Shah



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!