17

When wrapping simple HTML elements, take for example this MyLink tag:

// MyLink.tsx
import React from 'react';
import { Omit } from 'type-zoo';

interface MyLinkProps
  extends Omit<?, 'href'> {
  to: string;
  children: React.ReactNode;
}

export const MyLinkProps: React.FC<MyLinkProps> = ({
  children,
  to,
  ...attributes
}) => (
  <a href={to} {...attributes}>
    {children}
  </a>
);

// Elsewhere
<MyLink to="https://example.com">Example</MyLink>

It seems I can swap out the ? with any of the following:

  • React.HTMLProps<HTMLAnchorElement>
  • React.HTMLAttributes<HTMLAnchorElement>
  • React.AnchorHTMLAttributes<HTMLAnchorElement>

But what should one actually be using here? And if it varies, how does one choose?

2 Answers 2

28

I would say React.HTMLProps<HTMLAnchorElement> since this is the most descriptive type. For example if you wanted to provide a ref property to your anchor tag, you would need to use this type.

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

4 Comments

That seems sensible, and works for e.g. <a> tags. 👍 What confused me was that it didn't work for <svg>. After some more fiddling, it seems the equivalent there must be React.SVGProps<SVGSVGElement>, but yeah. Do you know of any good React Typescript type overviews? Doesn't really seem mentioned at all in the documentation.
This is my goto resource for react typings: github.com/piotrwitek/react-redux-typescript-guide
Thank you! Based on another SO post specifically about Divs, I had been using React.HTMLAttributes<HTMLAnchorElement> which seems to accept all html attributes EXCEPT for href. All I can gather is that React.HTMLProps allows a super set of attributes.
when I provide a ref to my anchor tag and use React.HTMLProps<HTMLAnchorElement> in my example, I get an error. Doesn't happen with React.HTMLAttributes or React.AnchorHTMLAttributes. I'm wrapping my element in styled component, though. But I always use React.AnchorHTMLAttributes<HTMLAnchorElement> instead of what you suggest.
7

I would choose React.AnchorHTMLAttributes<HTMLAnchorElement> even if you are simply wrapping html elements because it is the interface that extends the most and can guard against typescript errors

In this example, I'm wrapping an html <a> element in styled component.

MyLink.tsx:

import { forwardRef, AnchorHTMLAttributes, HTMLAttributes, HTMLProps } from 'react'
import styled, { StyledComponent } from '@emotion/styled'
import { EmotionJSX } from '@emotion/react/types/jsx-namespace'

type AnchorProps = AnchorHTMLAttributes<HTMLAnchorElement>
// type AnchorProps = HTMLAttributes<HTMLAnchorElement>
// type AnchorProps = HTMLProps<HTMLAnchorElement> // <~ THIS CAUSE ERROR

const StyledAnchor: StyledComponent<AnchorProps> = styled.a`
  color: red;
`

export default forwardRef<
  HTMLAnchorElement,
  AnchorHTMLAttributes<HTMLAnchorElement>
>((props: AnchorProps): EmotionJSX.Element => <StyledAnchor {...props} />)


// Elsewhere

const ref = useRef<HTMLAnchorElement>(null)

<MyLink ref={ref} href="/">my link</MyLink>

if I choose React.HTMLProps<HTMLAnchorElement>, then I will get typescript error:

Type 'StyledComponent<{ theme?: Theme | undefined; as?: ElementType<any> | undefined; }, DetailedHTMLProps<AnchorHTMLAttributes<HTMLAnchorElement>, HTMLAnchorElement>, {}>' is not assignable to type 'StyledComponent<AnchorProps, {}, {}>'.
  Types of property 'propTypes' are incompatible.
    Type 'WeakValidationMap<{ theme?: Theme | undefined; as?: ElementType<any> | undefined; } & ClassAttributes<HTMLAnchorElement> & AnchorHTMLAttributes<HTMLAnchorElement>> | undefined' is not assignable to type 'WeakValidationMap<AnchorProps> | undefined'.
      Type 'WeakValidationMap<{ theme?: Theme | undefined; as?: ElementType<any> | undefined; } & ClassAttributes<HTMLAnchorElement> & AnchorHTMLAttributes<HTMLAnchorElement>>' is not assignable to type 'WeakValidationMap<AnchorProps>'.
        Types of property 'as' are incompatible.
          Type 'Validator<ElementType<any> | null | undefined> | undefined' is not assignable to type 'Validator<string | null | undefined> | undefined'.
            Type 'Validator<ElementType<any> | null | undefined>' is not assignable to type 'Validator<string | null | undefined>'.
              Type 'ElementType<any> | null | undefined' is not assignable to type 'string | null | undefined'.
                Type 'ComponentClass<any, any>' is not assignable to type 'string'.ts(2322)

So I always use React.AnchorHTMLAttributes<HTMLAnchorElement>

Here are the react type interfaces:

  • interface HTMLProps<T> extends AllHTMLAttributes<T>, ClassAttributes<T>
  • interface HTMLAttributes<T> extends AriaAttributes, DOMAttributes<T>
  • interface AnchorHTMLAttributes<T> extends HTMLAttributes<T>

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.