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

时间:2016-10-17 18:55:08

标签: typescript jsx

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

使用the TypeScript documentation for merging interfaces,我认为我可以这样做:

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

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

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

  

[ts]财产&#39;阻止&#39;类型&#39; HTMLProps&#39;。

上不存在

他们所引用的HTMLPropsReact.HTMLProps<T>,并声明div元素使用它,如下所示:

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

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

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

编辑:以下是最终为我工作的内容:

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

5 个答案:

答案 0 :(得分:6)

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

declare namespace React {

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

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

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

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>
    )
};

显然这非常繁琐,您可以将扩充代码放在另一个文件中,如typescript手册中的示例所示,并导入它:

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

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

答案 1 :(得分:5)

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

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

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

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

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

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

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

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

export default createElement

然后告诉TS使用我们的createElement用于JSX和这个tsconfig:

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

用法:

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

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

答案 2 :(得分:1)

带有 TSX 的 Vue 3

// src/index.d.ts

import * as vue from 'vue';
declare module 'vue' {
  interface HTMLAttributes {
    className?: string;
    vHtml?: string;
    frameBorder?: string;
  }
}

答案 3 :(得分:0)

最新示例(2019年5月)

反应类型定义文件(默认情况下,当与(TIMESTAMPDIFF(SQL_TSI_DAY, "Sailtime"."SailTime Begin Date","Sailtime"."SailTime End Date")-(TIMESTAMPDIFF(SQL_TSI_DAY, "Sailtime"."SailTime Begin Date","Sailtime"."SailTime End Date")/365)*365)/30 配合时为index.d.ts)包含所有标准HTML元素以及已知属性的列表。

为了允许自定义HTML属性,您需要定义其输入。 通过扩展create-react-app界面来做到这一点:

HTMLAttributes

答案 4 :(得分:0)

对于vue,以下工作原理:

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