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

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


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

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

1
2
3
4
5
6
7
interface HTMLElement {
    block?: BEM.Block;
    element?: BEM.Element;
    modifiers?: BEM.Modifiers;
}

; // error

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

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

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

1
2
3
4
5
namespace JSX {
    interface IntrinsicElements {
        div: React.HTMLProps<HTMLDivElement>
    }
}

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

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

编辑:这就是最终对我有用的东西:

1
2
3
4
5
6
7
declare module ‘react’ {
    interface HTMLAttributes< T > extends DOMAttributes< T > {
        block?: string
        element?: string
        modifiers?: Modifiers // <– custom interface
    }
}
  • @MadaraUchiha extending React.HTMLProps<T> 怎么样?或者甚至将声明与 React.HTMLProps<T> 合并?
  • @ZevSpitz 我都试过了,但效果不好。扩展没有帮助,因为我不能强迫它使用我的界面,它只会使用 React.HTMLProps<T>,而合并声明根本不起作用,它完全忽略了它们。如果您可以证明它确实有效,请考虑将其发布为答案。
  • @MadaraUchiha 合并声明根本不起作用我想你的意思是 namespace React { interface HTMLProps<T> { /*custom elements here*/ } }?我不知道 HTMLProps 声明是什么样的,可能需要匹配它。
  • 我有一个问题:为什么需要这个?使用 data-* 属性有问题吗?
  • 你可以创建游乐场、codepen 或 jsfiddle 吗?


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

1
2
3
4
5
declare namespace React {

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

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

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

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
import * as React from ‘react’;

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

}

export const Foo = () => {

    return (
       
       
    )
};

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

1
2
import * as React from ‘react’;
import ‘./react_augmented’;

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

  • 谢谢!与此同时,我们以另一种方式解决了这个问题,但这是一个详细的答案,其中包含解决问题所需的一切。你有我的 1 和赏金。做得好! :)
  • @Madara\\’sGhost 你能分享一下你解决这个问题的另一种方法吗?
  • @nishanths 我不能,因为我什至不记得我在什么情况下遇到了这个特殊问题。对不起。


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

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

1
2
3
4
5
6
7
8
9
declare module ‘react’ {
  interface HTMLAttributes< T > {
    css?: any
  }

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

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

1
2
3
4
5
6
7
8
9
10
11
12
13
14
// 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 和这个 tsconfig:

1
2
3
4
5
6
{
 “compilerOptions”: {
   “jsx”:”react”,
   “jsxFactory”:”createElement”
  }
}

用法:

1
2
3
4
5
6
// MyComponent.tsx
import createElement from ‘./createElement’

export default function MyComponent() {
  return
}


最新示例(2019 年 5 月)

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

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

1
2
3
4
5
6
declare module ‘react’ {
  interface HTMLAttributes< T > extends AriaAttributes, DOMAttributes< T > {
    // extends React’s HTMLAttributes
    custom?: string;
  }
}

带有 TSX 的 Vue 3

1
2
3
4
5
6
7
8
9
10
// src/index.d.ts

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


从 React TypeScript Cheatsheet 添加非标准属性

1
2
3
4
5
6
7
8
// react-unstable-attributes.d.ts
import”react”;

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


对于 vue,以下工作:

1
2
3
4
5
6
declare module ‘vue-tsx-support/types/dom’ {
    interface InputHTMLAttributes  {
        autocorrect: string;
        autocapitalize
    }
}
  • 你有任何有效的例子吗?


来源:https://www.codenong.com/40093655/

微信公众号
手机浏览(小程序)

Warning: get_headers(): SSL operation failed with code 1. OpenSSL Error messages: error:14090086:SSL routines:ssl3_get_server_certificate:certificate verify failed in /mydata/web/wwwshanhubei/web/wp-content/themes/shanhuke/single.php on line 57

Warning: get_headers(): Failed to enable crypto in /mydata/web/wwwshanhubei/web/wp-content/themes/shanhuke/single.php on line 57

Warning: get_headers(https://static.shanhubei.com/qrcode/qrcode_viewid_9171.jpg): failed to open stream: operation failed in /mydata/web/wwwshanhubei/web/wp-content/themes/shanhuke/single.php on line 57
0
分享到:
没有账号? 忘记密码?