I am trying to enforce certain properties of a component depending on the type of the component... Basically I have a main interface with heroStyling types:
export type HeroStyling = 'SimpleForm' | 'WithTickerHeader' | 'WithTagLineHeader' | 'WithRating'
export interface AdaptiveHeroMainProps {
heroStyling: HeroStyling
cta: string
ctaUrl: string
image: FluidObject
imageAlt: string
}
and I am extending this to four other classes depending on the type of the heroStyling key:
export interface AdaptiveHeroMainProps {
heroStyling: HeroStyling
cta: string
ctaUrl: string
image: FluidObject
imageAlt: string
}
export interface WithTagLineHeader extends AdaptiveHeroMainProps {
headingTagLine: string
heading: string
leadParagraph: string
bulletPoints?: string
}
export interface WithTickerHeader extends AdaptiveHeroMainProps {
textCenter: boolean
leadParagraph?: string
bulletPoints?: string
}
export interface SimpleForm extends AdaptiveHeroMainProps {
textCenter: boolean
heading: string
leadParagraph?: string
bulletPoints?: string
}
export interface WithRating extends AdaptiveHeroMainProps {
textCenter: true
reviewStars?: boolean
}
My question is how can I enforce an extended class properties depending on what the type heroStyling is on my component without TypeScript complaining about one property not existing on a type? I need to deconstruct all props as I render according to their truthy or falsey values.
const CampaignHero = ({
heroStyling, textCenter, reviewStars, headingTagLine,
heading, leadParagraph, bulletPoints, cta, ctaUrl, image, imageAlt }
: WithTagLineHeader | WithTickerHeader | SimpleForm | WithRating ): React.ReactElement => {
return (
<section>
{headingTagLine && (
<div
dangerouslySetInnerHTML={{ __html: headingTagLine }}
/>
)}
{heading && <h1>{heading}</h1>}
{leadParagraph && <p>{leadParagraph}</p>}
{bulletPoints && (
<div
dangerouslySetInnerHTML={{ __html: bulletPoints }}
/>
)}
<Button href={ctaUrl}>{cta}</Button>
{reviewStars && (
<HeroRating />
)}
</div>
<Img alt={imageAlt} fluid={image} loading="eager" />
</section>
)
}
Question after captain-yossarian great help: If I render the component as below I get no errors but I should since bulletPoints is not part of the WithRating interface. TS complains only when one of the defined interface properties is missing, not when there is one that shouldn't exist.
<AdaptiveHero
heroStyling={'WithRating'}
reviewStars={true}
textCenter={true}
cta={hero.cta}
ctaUrl={hero.ctaUrl}
image={hero.image.fluid}
imageAlt={hero.image.alt}
bulletPoints={hero.bulletPoints}
/>