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

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.