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

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

有人知道如何正确 add/extend 所有原生 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] Property 'block' does not exist on type 'HTMLProps'.

他们所指的 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
    }
}

看起来在旧版本的类型定义文件 (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>
    )
};

显然这很繁琐,您可以将增强代码放在另一个文件中,如打字稿手册中的示例所示,然后导入它:

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

但还是很脏。因此,也许最好与类型定义文件的贡献者一起解决这个问题。

我想使用 glamour 的 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

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

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

用法:

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

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

一个 up-to-date 示例(2019 年 5 月)

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

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

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

对于 vue,以下工作:

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

带有 TSX 的 Vue 3

// src/index.d.ts

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

添加来自 React TypeScript Cheatsheet

的非标准属性
// react-unstable-attributes.d.ts
import "react";

declare module "react" {
  interface ImgHTMLAttributes<T> extends HTMLAttributes<T> {
    loading?: "auto" | "eager" | "lazy";
  }
}