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. =)