I am passing a prop which can be string or an object to a react functional component, an example below. It works without typescript. But, when I add typescript, it does not seem to understand that the prop (e.g. helpMessage below) can be either string or an object.
I get this error
TS2339: Property 'message' does not exist on type 'string | HelpMessage'. Property 'message' does not exist on type 'string'.
import React, { FC } from 'react';
interface HelpMessage {
headerText?: string;
footerText?: string;
message?: string;
}
interface FieldProps {
name: string;
helpMessage?: string | HelpMessage;
}
const ConditionalPropsComponent: FC<FieldProps> = ({ name, helpMessage }) => {
const helpMessageIsString = typeof helpMessage === 'string';
const helpText =
helpMessage && helpMessageIsString ? helpMessage : helpMessage?.message;
return (
<div>
{helpText && !helpMessageIsString && (
<div>
<p>{helpMessage?.headerText}</p>
<p>{helpMessage?.message}</p>
<p>{helpMessage?.footerText}</p>
</div>
)}
{helpText && helpMessageIsString && <p>{helpText}</p>}
</div>
);
};
export default ConditionalPropsComponent;
The error appears where the red wiggly lines are in the screenshot below:
I created a code sandbox, so that you can see the issue. https://codesandbox.io/s/github/nfabacus/React-typescript-dynamic-type-issue/tree/main/?file=/src/index.tsx:217-226
Basically, extracting the condition to const helpMessageIsString = typeof helpMessage === 'string'; throws the type error, but if I replace every one of them with typeof helpMessage === 'string', error disappears, but this is repetitive..
also, below works but feels hacky - helpMessage is either HelpMessage or undefined. When I pass string, it is neither the HelpMessage object or undefined, but typescript does not complain..which is strange.
interface HelpMessage {
headerText?: string;
footerText?: string;
message?: string;
}
interface FieldProps {
name: string;
helpMessage?: HelpMessage;
}
const ConditionalPropsComponent: React.FC<FieldProps> = ({
name,
helpMessage
}) => {
const helpMessageIsString = typeof helpMessage === 'string';
const helpText = helpMessageIsString ? helpMessage : helpMessage?.message;
....
Typescript is great, but in this particular case, I feel a bit disappointed with Typescript, if there is not a good solution for this...

ifblock instead, the compiler may interrupt it then. In any case you can make reproducible example in TS playground and show us the error.