如何向 TypeScript/JSX 中的现有 HTML 元素添加属性?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/40093655/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-21 03:56:19  来源:igfitidea点击:

How do I add attributes to existing HTML elements in TypeScript/JSX?

typescriptjsx

提问by jedmao

Anyone know how to properly add/extend all native HTML element attributes with custom ones?

任何人都知道如何使用自定义属性正确添加/扩展所有本机 HTML 元素属性?

With the TypeScript documentation for merging interfaces, I thought that I could just do this:

使用用于合并接口的 TypeScript 文档,我认为我可以这样做:

interface HTMLElement {
    block?: BEM.Block;
    element?: BEM.Element;
    modifiers?: BEM.Modifiers;
}

<div block="foo" />; // error

But I get the following Intellisense error in vscode 1.6.1 (latest):

但是我在 vscode 1.6.1(最新)中收到以下 Intellisense 错误:

[ts] Property 'block' does not exist on type 'HTMLProps'.

[ts] 'HTMLProps' 类型不存在属性 'block'。

The HTMLPropsto which they are referring is React.HTMLProps<T>and the divelement is declared to use it like so:

HTMLProps它们指是React.HTMLProps<T>div元素被声明为使用它像这样:

namespace JSX {
    interface IntrinsicElements {
        div: React.HTMLProps<HTMLDivElement>
    }
}

I tried redeclaring the div, but to no avail.

我尝试重新声明div,但无济于事。

Related: https://github.com/Microsoft/TypeScript/issues/11684

相关:https: //github.com/Microsoft/TypeScript/issues/11684

Edit:Here's what ended up working for me:

编辑:这是最终对我来说有效的内容:

declare module 'react' {
    interface HTMLAttributes<T> extends DOMAttributes<T> {
        block?: string
        element?: string
        modifiers?: Modifiers // <-- custom interface
    }
}

采纳答案by Edwin

Looks like in older versions of type definition files (v0.14) the interfaces were simply declared under a global React namespace, so previously you could use the standard merging syntax.

看起来在旧版本的类型定义文件 (v0.14) 中,接口只是在全局 React 命名空间下声明,因此以前您可以使用标准合并语法。

declare namespace React {

    interface HTMLProps<T> extends HTMLAttributes, ClassAttributes<T> {
    }
}

However the new version of d.ts file (v15.0) have declared everything inside a module. Since modules do not support merging, to the best of my knowledge the only option right now seems to be module augmentation: https://www.typescriptlang.org/docs/handbook/declaration-merging.html

然而,新版本的 d.ts 文件 (v15.0) 已经在模块内声明了所有内容。由于模块不支持合并,据我所知,现在唯一的选择似乎是module augmentationhttps: //www.typescriptlang.org/docs/handbook/declaration-merging.html

I did the following experiment and it worked for me:

我做了以下实验,它对我有用:

import * as React from 'react';

declare module 'react' {
     interface HTMLProps<T> {
        block?:string;
        element?:string;
        modifiers?:string;
    }

}

export const Foo = () => {

    return (
        <div block="123" element="456">
        </div>
    )
};

Obviously this is quite tedious, you could put the augmentation code in another file as shown in the example from the typescript handbook, and import it:

显然这很乏味,您可以将扩充代码放在另一个文件中,如打字稿手册中的示例所示,然后将其导入:

import * as React from 'react';
import './react_augmented';

But it's still quite dirty. So maybe it's best to address the issue with the contributors of the type definition file.

但它仍然很脏。所以也许最好与类型定义文件的贡献者一起解决这个问题。

回答by jschr

I wanted to use glamor's createElementreplacement which adds a cssprop to every element.

我想使用 glamor 的createElement替换,它css为每个元素添加一个道具。

To add to the accepted answer, module augmentation seems to do the trick but HTMLPropsonly worked for non-input elements. The correct interfaces to extend seems to be HTMLAttributesand SVGAttributes.

要添加到已接受的答案中,模块增强似乎可以解决问题,但HTMLProps仅适用于非输入元素。要扩展的正确接口似乎是HTMLAttributesSVGAttributes

declare module 'react' {
  interface HTMLAttributes<T> {
    css?: any
  }

  interface SVGAttributes<T> {
    css?: any
  }
}

To avoid importing the module augmentation in every component, re-export createElement:

为避免在每个组件中导入模块扩充,请重新导出 createElement:

// createElement.ts
import { createElement } from 'glamor/react'

declare module 'react' {
  interface HTMLAttributes<T> {
    css?: any
  }

  interface SVGAttributes<T> {
    css?: any
  }
}

export default createElement

Then tell TS to use our createElementfor JSX with this tsconfig:

然后告诉 TScreateElement通过这个 tsconfig使用我们的for JSX:

{
  "compilerOptions": {
    "jsx": "react",
    "jsxFactory": "createElement"
  }
}

Usage:

用法:

// MyComponent.tsx
import createElement from './createElement'

export default function MyComponent() {
  return <div css={{ color: 'red' }} />
}

回答by yuval.bl

An up-to-date example (May 2019)

最新示例(2019 年 5 月)

React type definition file (by default - index.d.tswhen staring with create-react-app) contain list of all the standard HTML elements, as well as known attributes.

React 类型定义文件(默认情况下 -index.d.ts以开头时create-react-app)包含所有标准 HTML 元素的列表,以及已知属性。

In order to allow custom HTML attributes, you need to define it's typing. Do that by expanding HTMLAttributesinterface:

为了允许自定义 HTML 属性,您需要定义它的类型。通过扩展HTMLAttributes接口来做到这一点:

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

回答by Poul K. S?rensen

For vue, the following works:

对于 vue,以下工作:

declare module 'vue-tsx-support/types/dom' {
    interface InputHTMLAttributes  {
        autocorrect: string;
        autocapitalize
    }
}