Is it possible to allow DOM element properties to be extended when using a custom JSX pragma?
Similar to how emotion & styled-components use a css
prop and manage logic within their jsx pragmas. I would like to do the same, but with properties that can be configured via a generic type?
So, for example:
// @jsx jsx
import { jsx } from 'my-lib';
...
<button<{ primary: boolean }> css={styles} primary={primary}>
Hello world
</button>
My current type definition looks something like this:
interface CustomAttributes {
css?: CSSProperties;
}
declare module 'react' {
interface DOMAttributes extends CustomAttributes {}
}
declare global {
namespace JSX {
interface IntrinsicAttributes extends CustomAttributes {}
}
}
and my naive solution would look something like this:
interface CustomAttributes {
css?: CSSProperties;
}
declare module 'react' {
interface DOMAttributes<DynamicProps> extends CustomAttributes, DynamicProps {}
}
declare global {
namespace JSX {
interface IntrinsicAttributes<DynamicProps> extends CustomAttributes, DynamicProps {}
}
}
related question: Styled components's 'css' prop with TypeScript
You can definitely add a fixed set of properties but I can't figure out how to make it dynamic. This works just fine and adds an optional
boolean
property 'primary' to all JSX elements.When we try to make it generic we run into trouble because the original interface is not generic. Adding a generic
<T>
causes this error:There are a bunch of interfaces in the inheritance chain that react uses to determine props (
React.DetailedHTMLProps
), so there are other possible places that you could add your props.interface DOMAttributes<T>
,interface HTMLAttributes<T>
, etc. are generic, but the generic typeT
refers to the type of the element (ie.button
) rather than a generic argument of the element. It is possible to add certain props to allbutton
elements.The brick wall that I can't get past is how to make the
button
element itself generic like your example whenJSX.IntrinsicElements.button
is not generic. I'm not confident enough to say that it's definitely impossible, but I'm not able to do it.