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' }} />
}

Tags:

Typescript

Jsx