'React + TS: Using generic types to get HTML props based on tag name
I have a common use case where I want a component that is simply a styled HTML tag. For example, the following works fine for creating style divs:
// Definitions
const styledDiv = (className: string) => {
const StyledDiv = React.FC<HTMLAttributes<HTMLDivElement>> => props => {
return <div {...props} className={classNames(className, props.className)} />;
}
return StyledDiv;
}
// Usage
const Foo = styledDiv(styles.foo);
const Bar = () => {
return <Foo className={styles.bar} onClick={...} ... />
}
I am attempting to make this generic so that it will work for any HTML element, not just divs. I have tried the following:
// Definition
export const styledTag = <T extends keyof JSX.IntrinsicElements>(className: string, tag: T) => {
const Tag = tag;
const StyledTag: React.FC<HTMLAttributes<T>> = props => {
const classes = classNames(className, props.className);
return <Tag {...props} className={classes}/>;
};
return StyledTag;
};
// Desired usage:
const Foo = styledTag(styles.foo, 'div');
const Bar = styledTag(styles.bar, 'span');
const Baz = () => {
return (
<div>
<Foo ... />
<Bar ... />
</div>
);
}
Unfortunately, I am getting a Type X is not assignable to type Y error when I try to spread my props on the tag (<Tag {...props} />). Is there a way to accomplish this generically, or will I have to repeat this code for every HTML tag I want?
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|
