【问题标题】:Property does not exist on type 'DetailedHTMLProps, HTMLDivElement>' with React 16使用 React 16 的“DetailedHTMLProps,HTMLDivElement>”类型不存在属性
【发布时间】:2018-02-23 05:33:59
【问题描述】:

由于 React 16 现在允许 custom DOM attributes,我尝试在我的 Typescript 代码中利用它:

import * as React from 'react';

<div className="page" size="A4">
</div>

但收到此错误消息:

错误 TS2339:类型上不存在属性“大小” 'DetailedHTMLProps, HTMLDivElement>'.

这个thread建议做一个module augmentation,所以我这样尝试:

import * as React from 'react';

declare module 'react' {
     interface HTMLProps<T> {
        size?:string;
    }    
}

同样的错误信息。

最后,我还尝试将page声明为一个新的HTML标签:

declare global {
  namespace JSX {
    interface IntrinsicElements {
      page: any
    }
  }
}

<page className="page" size="A4">
</page>

它摆脱了错误消息,但 size 属性在编译代码中被完全忽略,我最终得到:

<page className="page">
</page>

理想情况下,最后一个是我的首选解决方案。我想在 page 自定义标签旁边使用 size 自定义属性。

tsconfig.js

{
  "compilerOptions": {
    "outDir": "build/dist",
    "module": "esnext",
    "target": "es5",
    "lib": ["es6", "dom"],
    "sourceMap": true,
    "allowJs": true,
    "jsx": "react",
    "moduleResolution": "node",
    "rootDir": "src",
    "forceConsistentCasingInFileNames": true,
    "noImplicitReturns": true,
    "noImplicitThis": true,
    "noImplicitAny": true,
    "strictNullChecks": true,
    "suppressImplicitAnyIndexErrors": true,
    "allowSyntheticDefaultImports": true,
    "noUnusedLocals": false,
    "noUnusedParameters": false,
    "allowUnusedLabels": true,
    "allowUnreachableCode": true
  }
}

【问题讨论】:

  • 我对 TypeScript 了解不多,但对于一个想法-可能很愚蠢-,试试data-size怎么样?
  • 哇...它摆脱了我的错误,并编译了!是什么让您想到了这一点,为什么与任何“非破折号”名称(例如大小)相比,它会起作用?你能把它写成答案让我验证吗?

标签: reactjs typescript


【解决方案1】:

HTML 支持自定义属性的 data-* 属性类型。你可以阅读更多here

定义和用法 data-* 属性用于存储自定义 页面或应用程序的私有数据。

data-* 属性使我们能够嵌入自定义数据 所有 HTML 元素的属性。

然后可以在页面的 JavaScript 中使用存储的(自定义)数据 创建更具吸引力的用户体验(无需任何 Ajax 调用或 服务器端数据库查询)。

data-* 属性由两部分组成:

  • 属性名称不能包含任何大写字母,并且必须 在前缀“data-”之后至少有一个字符
  • 属性值可以是任意字符串

注意:以“data-”为前缀的自定义属性将被用户代理完全忽略。

您可以使用data-size="A4",而不仅仅是使用size="A4"

示例

<div className="page" data-size="A4">
  // ....
</div>

【讨论】:

  • 它有效,但我不确定这是完整的解释:我尝试了 page-size 而不是 data-size,它也有效。我尝试使用“-”的任何名称似乎都有效,好像 Typescript 忽略了警告并强制编译。谢谢!
  • 就像我说的,我对 TypeScript 了解不多。可能有更好的解释。谢谢你的支持
【解决方案2】:

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

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

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

可能相关的问题:

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

【讨论】:

  • 我尝试导入 AriaAttributes、DOMAttributes 但得到了Circular definition of import alias 'AriaAttributes',其他导入也出现同样的错误
【解决方案3】:

如果您使用样式化组件,则可以更简单:

const App = props => {
  return <StyledDiv version={2.0}>My custom div</StyledDiv>
}

type Custom = {
  version?: number
}

const StyledDiv = styled.div<Custom>`
  // styles
`

【讨论】:

  • 非常感谢!
【解决方案4】:

不完全相关,但假设您想在自定义组件中接受额外的属性,使用像 ...rest 这样的扩展运算符。以下是你的做法:

interface Props{
  icon?: string; 
}

type Button = Props & React.HTMLProps<HTMLButtonElement> & React.HTMLAttributes<HTMLButtonElement>;

function Button({ 
  icon,
  ...rest
}: Button) {
  return (
    <button 
      {...rest}
    >
     {icon && <span>{icon}</span>}
     {children}       
    </button>
}

【讨论】:

    猜你喜欢
    • 2022-01-04
    • 2021-06-17
    • 2022-01-15
    • 1970-01-01
    • 2017-08-18
    • 2019-11-26
    • 2022-09-23
    • 2019-04-13
    • 2019-11-30
    相关资源
    最近更新 更多