8

I presume the TypeScript engine within Visual Studio Code has received an update that is now complaining for the first time that my pre-existing custom props on HTML elements are invalid. This is on a Babel/React/JSX project with no TypeScript whatsoever.

<div custom="bar" />

Note: they are (technically) invalid, but I consume them, so I know what I'm doing (it's intentional).

See it on CodePen!

See also

3

3 Answers 3

11

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:

import { HTMLAttributes } from "react";

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

Read more about module augmentation on TypeScript docs.

Sign up to request clarification or add additional context in comments.

2 Comments

This breaks typescript type checking for the 'react' module.
Don't forget to import HTMLAttributes
9

Note: If an attribute name is not a valid JS identifier (like a data-* attribute), it is not considered to be an error if it is not found in the element attributes type.

<div data-custom="bar" />

https://www.typescriptlang.org/docs/handbook/jsx.html#attribute-type-checking https://developer.mozilla.org/en-US/docs/Web/HTML/Global_attributes/data-*

4 Comments

add details to the answer
Welcome to Stack Overflow! Please don't just throw your source code here. Be nice and try to give a nice description to your answer, so that others will like it and upvote it. See: How do I write a good answer?
The answer was hyphens... all along? True heroes don't always wear capes! :)
@MobA11y The answer is not hyphens, custom-thing is still invalid. The answer is specifically data-* attributes. See here.
2

Project structure:

☁  extends-react-types  tree -I 'node_modules' 
.
├── App.tsx
├── index.d.ts
├── package-lock.json
├── package.json
└── tsconfig.json

0 directories, 5 files

package version:

{
  "name": "extends-react-types",
  "devDependencies": {
    "@types/react": "^16.9.56",
    "typescript": "^4.3.5"
  },
  "dependencies": {
    "react": "^16.8.6"
  }
}

tsconfig.json:

{
    "compilerOptions": {
        "target": "es5",
        "lib": [
            "dom"
        ],
        "allowSyntheticDefaultImports": true,
        "moduleResolution": "Node",
        "jsx": "preserve",
    }
}

App.tsx:

import React from 'react';

interface HomeProps extends React.ComponentPropsWithRef<'div'> {}
export default function Home(props: HomeProps) {
  return (
    <div>
      <p _name="name" _error={true}>
        123
      </p>
    </div>
  );
}

As you can see, there are two custom HTML attributes in p element: _name and _error. Now, we need to extend HTMLAttributes interface of React with these two custom HTML attributes.

Option 1:

index.d.ts:

import 'react';

declare module 'react' {
  interface HTMLAttributes<T> extends AriaAttributes, DOMAttributes<T> {
    _name?: string;
    _error?: boolean;
  }
}

Output:

enter image description here

Option 2:

declare namespace React {
  interface HTMLAttributes<T> extends AriaAttributes, DOMAttributes<T> {
    _name?: string;
    _error?: boolean;
  }
}

Output:

enter image description here

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.