skip to Main Content

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

2

Answers


  1. Your code is partial and I’m not sure what CardProps is, I made a scaled down example that seems to work. You can find it here.

    Login or Signup to reply.
  2. 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
    };
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search