Search code examples
reactjstypescriptreact-typescript

How to type narrow JSX.Element


I'd like to have a variable that can be either a React component or a string, like this:

function MyComponent(): JSX.Element {
  let icon: JSX.Element | string = "/example.png";  // (simplified)

  return <div>{typeof icon === "JSX.Element" ? icon : <img src={icon} />}</div>;
}

however TS complains about my condition saying:

TS2367: This condition will always return 'false' since the types '"string" | "number" | "bigint" | "boolean" | "symbol" | "undefined" | "object" | "function"' and '"JSX.Element"' have no overlap.

What should I do?


Solution

  • The typeof operator cannot return "JSX.Element". It can only return the string types listed in that error message:

    "string" | "number" | "bigint" | "boolean" | "symbol" | "undefined" | "object" | "function"
    

    Which means that you will need to check against something in that list, like "string".

    function MyComponent(): JSX.Element {
      let icon: JSX.Element | string = "/example.png";
      
      return <div>{typeof icon === "string" ? <img src={icon} /> : icon }</div>;
    }