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?
As of React 16, any standard or custom DOM attributes are fully supported. These props work similarly to the corresponding HTML attributes, with the exception of the special cases documented above. You may also use custom attributes as long as they're fully lowercase.
To extend an HTML Element in a component's props in React, extend the specific element type in the props interface of your component, e.g. interface ButtonProps extends React. ButtonHTMLAttributes<HTMLButtonElement> {} . Copied! import React from 'react'; interface ButtonProps extends React.
Using the extends keyword, you can allow the current component to access all the component's properties, including the function, and trigger it from the child component. This example creates one component called ParentClass. jsx. ParentClass extends the component from React as React.
const {a, b, c} = props; const htmlProps = rest(props, {a, b, c}); And once TypeScript supports object rest/spread I can just look for all usages of rest() and simplify it to const {a, b, c, ... htmlProps} = props . Save this answer.
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.
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>
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With