How do I add attributes to existing HTML elements in TypeScript/JSX?
Looks like in older versions of type definition files (v0.14) the interfaces were simply declared under a global React namespace, so previously you could use the standard merging syntax.
declare namespace React {
interface HTMLProps<T> extends HTMLAttributes, ClassAttributes<T> {
}
}
However the new version of d.ts file (v15.0) have declared everything inside a module. Since modules do not support merging, to the best of my knowledge the only option right now seems to be module augmentation
:
https://www.typescriptlang.org/docs/handbook/declaration-merging.html
I did the following experiment and it worked for me:
import * as React from 'react';
declare module 'react' {
interface HTMLProps<T> {
block?:string;
element?:string;
modifiers?:string;
}
}
export const Foo = () => {
return (
<div block="123" element="456">
</div>
)
};
Obviously this is quite tedious, you could put the augmentation code in another file as shown in the example from the typescript handbook, and import it:
import * as React from 'react';
import './react_augmented';
But it's still quite dirty. So maybe it's best to address the issue with the contributors of the type definition file.
I wanted to use glamor's createElement replacement which adds a css
prop to every element.
To add to the accepted answer, module augmentation seems to do the trick but HTMLProps
only worked for non-input elements. The correct interfaces to extend seems to be HTMLAttributes
and SVGAttributes
.
declare module 'react' {
interface HTMLAttributes<T> {
css?: any
}
interface SVGAttributes<T> {
css?: any
}
}
To avoid importing the module augmentation in every component, re-export createElement:
// createElement.ts
import { createElement } from 'glamor/react'
declare module 'react' {
interface HTMLAttributes<T> {
css?: any
}
interface SVGAttributes<T> {
css?: any
}
}
export default createElement
Then tell TS to use our createElement
for JSX with this tsconfig:
{
"compilerOptions": {
"jsx": "react",
"jsxFactory": "createElement"
}
}
Usage:
// MyComponent.tsx
import createElement from './createElement'
export default function MyComponent() {
return <div css={{ color: 'red' }} />
}