如何使用 Typescript 在 React 中扩展 HTML 属性

Posted

技术标签:

【中文标题】如何使用 Typescript 在 React 中扩展 HTML 属性【英文标题】:How to extend HTML attributes in React with Typescript 【发布时间】:2019-09-17 10:21:34 【问题描述】:

当包装简单的 html 元素时,以 MyLink 标签为例:

// 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>

看来我可以将? 换成以下任何一种:

React.HTMLProps&lt;HTMLAnchorElement&gt; React.HTMLAttributes&lt;HTMLAnchorElement&gt; React.AnchorHTMLAttributes&lt;HTMLAnchorElement&gt;

但实际上应该在这里使用什么?如果不同,如何选择?

【问题讨论】:

【参考方案1】:

我会选择React.AnchorHTMLAttributes&lt;HTMLAnchorElement&gt;,即使你只是简单地包装html元素,因为它是扩展最多的接口并且可以防止打字稿错误

在此示例中,我将一个 html &lt;a&gt; 元素包装在样式组件中。

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>

如果我选择React.HTMLProps&lt;HTMLAnchorElement&gt;,那么我会得到打字稿错误:

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)

所以我总是用React.AnchorHTMLAttributes&lt;HTMLAnchorElement&gt;

这里是 react 类型的接口:

interface HTMLProps&lt;T&gt; extends AllHTMLAttributes&lt;T&gt;, ClassAttributes&lt;T&gt; interface HTMLAttributes&lt;T&gt; extends AriaAttributes, DOMAttributes&lt;T&gt; interface AnchorHTMLAttributes&lt;T&gt; extends HTMLAttributes&lt;T&gt;

【讨论】:

【参考方案2】:

我会说React.HTMLProps&lt;HTMLAnchorElement&gt;,因为这是最具描述性的类型。例如,如果您想为锚标记提供 ref 属性,则需要使用此类型。

【讨论】:

这似乎很明智,适用于例如&lt;a&gt; 标签。 ? 让我感到困惑的是它不适用于&lt;svg&gt;。经过一番摆弄之后,似乎必须有React.SVGProps&lt;SVGSVGElement&gt;,但是是的。你知道任何好的 React Typescript 类型概述吗?文档中似乎根本没有提到。 这是我用于响应类型的 goto 资源:github.com/piotrwitek/react-redux-typescript-guide 谢谢!基于另一篇专门关于 Divs 的 SO 帖子,我一直在使用 React.HTMLAttributes&lt;HTMLAnchorElement&gt;,它似乎接受除了 href 之外的所有 html 属性。我只能收集到 React.HTMLProps 允许一组超级属性。 当我向我的锚标签提供ref 并在我的示例中使用React.HTMLProps&lt;HTMLAnchorElement&gt; 时,我收到错误消息。 React.HTMLAttributesReact.AnchorHTMLAttributes 不会发生这种情况。不过,我将元素包装在样式组件中。但我总是使用React.AnchorHTMLAttributes&lt;HTMLAnchorElement&gt; 而不是您的建议。

以上是关于如何使用 Typescript 在 React 中扩展 HTML 属性的主要内容,如果未能解决你的问题,请参考以下文章

如何在 React+Typescript 中使用微数据?

如何在 TypeScript 中使用带有 React 无状态功能组件的子组件?

如何使用 Typescript 在 React 中扩展 HTML 属性

React-native:如何在 React-native 中使用(和翻译)带有 jsx 的 typescript .tsx 文件?

你如何在带有 Typescript 的 create-react-app 中使用 Mocha?

在react typescript项目中如何使用没有@type定义的npm包