Differences Between HTMLAttributes and DOMAttributes in Typescript

This article assumes you are familiar with basic TypeScript & React

Imagine you wanted a React component that just spits out a native HTML button. That’s simple, You could do this

const Button = props => {
  const { children } = props
  return <button {...props}>{children}</button>
}

If the project is large and more long-term, there’s a chance you’re using TypeScript. Your code might look like this

interface ButtonProps {
    ...
}
const Button: FC<ButtonProps> = (props) => {
    const {children} = props
    return <button>{children}</button>
}

Using your Component cannot be any easier

<Button>I'm a Button</Button>

The Problem

We should be able to pass in attributes of a native HTML button, like styles, onClick, etc. But here’s what happens when we try to

This is because our fancy Button element has no knowledge it’s rendering a native button element.

The Solution

TypeScript gives us a way to extend attributes for native HTML elements. I’ve seen a lot of ways to do this, but DOMAttributes<HTMLButtonElement> and HTMLAttributes<HTMLButtonElement> seem to be the most used. Here’s some example

interface ButtonProps extends DOMAttributes<HTMLButtonElement> {}

or

interface ButtonProps extends HTMLAttributes<HTMLButtonElement> {}

So What Should I Use?

If you look into the TypeScript declaration file for React (node_modules/react/react.d.ts), you’ll find this line of code

interface HTMLAttributes<T> extends AriaAttributes, DOMAttributes<T> {...}

This makes it clear which you should use now; HTMLAttributes is DOMAttributes plus AriaAttributes.

Thanks for reading😊