I'm trying to create an object that can be spread into a React Component and this object has to include an HTML Custom Data Attribute.
import { HTMLAttributes } from 'react'
interface FooProps extends HTMLAttributes<HTMLButtonElement> {
fooProp: string
//'data-testid': string // do HTML Custom Attributes not come out of the box?
}
const fooObj: FooProps = {
fooProp: 'yay',
'data-testid': 'nay' // Object literal may only specify known properties, and ''data-testid'' does not exist in type 'Foo'.(2353)
}
const Foo = () => <button {...fooObj}></button>
In the example above, I can't seem to type my object to allow for custom data attributes without having to explicitly list them out. How do I type the object to allow for custom data attributes without explicit declarations?
Although custom data attributes
data-*are recognized by the TypeScript compiler when using JSX syntax — e.g. this compiles without error…TS Playground
…React does not provide element attribute type aliases/interfaces which include them.
In order to allow for custom data attributes in your own types, you can either include them explicitly at each definition…
TS Playground
…or — you can approach it in a much more DRY way by using the pattern of module augmentation:
Create a type declaration file in your project at a path that is included in your program's compilation (e.g.
src/types/react_data_attributes.d.ts):Then, at each usage site, the explicit intersection will no longer be needed:
TS Playground
A note regarding
HTMLElementsubtypes:Each subtype (e.g.
<button>,<a>, etc.) might have specialized attributes in addition what's offered in the baseHTMLAttributes, so you'll need to type your element attributes accordingly for the compiler to recognize those specific attributes. Here's an example showing some of the specialized attributes for the elements above:TS Playground