Property does not exist on type 'DetailedHTMLProps, HTMLDivElement>' with React 16

ReactjsTypescript

Reactjs Problem Overview


Since React 16 now allows custom DOM attributes, I tried to leverage this in my Typescript code:

import * as React from 'react';

<div className="page" size="A4">
</div>

but receive this error message:

> error TS2339: Property 'size' does not exist on type > 'DetailedHTMLProps< HTMLAttributes< HTMLDivElement>, HTMLDivElement>'.

This thread suggests to do a module augmentation, so I tried this way:

import * as React from 'react';

declare module 'react' {
     interface HTMLProps<T> {
        size?:string;
    }    
}

Same error message.

Finally, I also tried to declare page as a new HTML tag:

declare global {
  namespace JSX {
    interface IntrinsicElements {
      page: any
    }
  }
}

<page className="page" size="A4">
</page>

It gets rid of the error message, but the size attribute is completely ignored in the compiled code, and I end up with:

<page className="page">
</page>

Ideally, the last one is my preferred solution. I'd like to use the size custom attribute alongside the page custom tag.

> tsconfig.js

{
  "compilerOptions": {
    "outDir": "build/dist",
    "module": "esnext",
    "target": "es5",
    "lib": ["es6", "dom"],
    "sourceMap": true,
    "allowJs": true,
    "jsx": "react",
    "moduleResolution": "node",
    "rootDir": "src",
    "forceConsistentCasingInFileNames": true,
    "noImplicitReturns": true,
    "noImplicitThis": true,
    "noImplicitAny": true,
    "strictNullChecks": true,
    "suppressImplicitAnyIndexErrors": true,
    "allowSyntheticDefaultImports": true,
    "noUnusedLocals": false,
    "noUnusedParameters": false,
    "allowUnusedLabels": true,
    "allowUnreachableCode": true
  }
}

Reactjs Solutions


Solution 1 - Reactjs

HTML supports data-* attribute type for custom attributes. You can read about it more here.

> Definition and Usage The data-* attributes is used to store custom > data private to the page or application. > > The data-* attributes gives us the ability to embed custom data > attributes on all HTML elements. > > The stored (custom) data can then be used in the page's JavaScript to > create a more engaging user experience (without any Ajax calls or > server-side database queries). > > The data-* attributes consist of two parts: > > - The attribute name should not contain any uppercase letters, and must > be at least one character long after the prefix "data-" > - The attribute value can be any string
>
> Note: Custom attributes prefixed with "data-" will be completely ignored by the user agent.

Rather than just using size="A4" you can use data-size="A4"

Example

<div className="page" data-size="A4">
  // ....
</div>

Solution 2 - Reactjs

React type definition file (by default - index.d.ts when staring with create-react-app) contain list of all the standard HTML elements, as well as known attributes.

In order to allow custom HTML attributes, you need to define it's typing. Do that by expanding HTMLAttributes interface:

declare module 'react' {
  interface HTMLAttributes<T> extends AriaAttributes, DOMAttributes<T> {
    // extends React's HTMLAttributes
    custom?: string;
  }
}

Possibly related question:

https://stackoverflow.com/questions/40093655/how-do-i-add-attributes-to-existing-html-elements-in-typescript-jsx/56109822#56109822

Solution 3 - Reactjs

If you are using styled-components, you can do it even simplier:

const App = props => {
  return <StyledDiv version={2.0}>My custom div</StyledDiv>
}

type Custom = {
  version?: number
}

const StyledDiv = styled.div<Custom>`
  // styles
`

Solution 4 - Reactjs

Not entirely related, but say you want to accept extra attributes in your custom component, using the spread operator like ...rest. Here´s how you do it:

interface Props{
  icon?: string; 
}

type Button = Props & React.HTMLProps<HTMLButtonElement> & React.HTMLAttributes<HTMLButtonElement>;

function Button({ 
  icon,
  ...rest
}: Button) {
  return (
    <button 
      {...rest}
    >
     {icon && <span>{icon}</span>}
     {children}       
    </button>
}

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionGreg ForelView Question on Stackoverflow
Solution 1 - ReactjsbennygenelView Answer on Stackoverflow
Solution 2 - Reactjsyuval.blView Answer on Stackoverflow
Solution 3 - ReactjsZiiMakcView Answer on Stackoverflow
Solution 4 - ReactjsmayidView Answer on Stackoverflow