Specify certain html tags as generic styled component in typescript

Viewed 348

I tried to build a generic emotion styled component as headline in react with typescript. The goal is to dynamically pass the html tag as props, which should only be an "h1" | "h2" | "h3" | "h4" | "h5" | "h6". This is my code:

interface Props extends StyledProps {
    tag: keyof JSX.IntrinsicElements; // TODO specify only heading
}

export const CenteredHeadline: React.FC<Props> = ({
    tag,
    fontSizeMobile,
    fontSizeDesktop,
    children,
}) => {
    const StyledComponent = styled(tag)<StyledProps>`
        label: CenteredHeadline;
        color: #3f4846;
        font-size: ${(props) => (props.fontSizeMobile ? 'props.fontSizeMobile' : '34px')};
        text-align: center;

        @media screen and (min-width: 768px) {
            font-size: ${(props) => (props.fontSizeDesktop ? 'props.fontSizeDesktop' : '40px')};
            max-width: 750px;
        }
    `;
    return (
        <StyledComponent fontSizeMobile={fontSizeMobile} fontSizeDesktop={fontSizeDesktop}>
            {children}
        </StyledComponent>
    );
};

The above code works fine so far, but the tag prop is not limited to only being a heading.

I tried something like this

interface Props extends StyledProps {
    tag:
        | JSX.IntrinsicElements['h1']
        | JSX.IntrinsicElements['h2']
        | JSX.IntrinsicElements['h3']
        | JSX.IntrinsicElements['h4']
        | JSX.IntrinsicElements['h5']
        | JSX.IntrinsicElements['h6']; // TODO specify only heading
}

which lead to a bunch of errors in my emotion prop (tag).

So the question is more typescript related, I guess:

Is there a way to specify certain keys in keyof something, JSX.IntrinsicElements in my case?

Thanks for any help!

UPDATE

I find a way to specify the keys:

type Tag = Pick<JSX.IntrinsicElements, "h1" | "h2">

 const StyledComponent = styled<Tag>(tag)<StyledProps>`
  ...

But I'll get an error in my styled component saying

Type 'Tag' does not satisfy the constraint 'keyof IntrinsicElements'

So I guess the problem ships to emotion now.

I'm still happy for any tips here. =)

1 Answers

Why not simply: type Tag = "h1" | "h2" | "h3" | ....

Related