如何向 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
How do I add attributes to existing HTML elements in TypeScript/JSX?
提问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 HTMLProps
to which they are referring is React.HTMLProps<T>
and the div
element 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 augmentation
:https:
//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 css
prop to every element.
我想使用 glamor 的createElement替换,它css
为每个元素添加一个道具。
To add to the accepted answer, module augmentation seems to do the trick but HTMLProps
only worked for non-input elements. The correct interfaces to extend seems to be HTMLAttributes
and SVGAttributes
.
要添加到已接受的答案中,模块增强似乎可以解决问题,但HTMLProps
仅适用于非输入元素。要扩展的正确接口似乎是HTMLAttributes
和SVGAttributes
。
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 createElement
for 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.ts
when 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 HTMLAttributes
interface:
为了允许自定义 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
}
}