TypeScript 报告了 button 元素的 form 属性上的错误。

huangapple go评论77阅读模式
英文:

TypeScript reports error on form attribute of button element

问题

尽管在HTML按钮元素的MDN页面中有一个form属性,用于将提交按钮连接到其所属的表单(它们不需要在父子层次结构中),但当我创建一个像这样的按钮时,TypeScript会给我报错:

<button type='submit' form='createCustomerForm'>

这是完整的TypeScript错误消息:

TS2322: 类型 'string | HTMLFormElement | null' 不能分配给类型 'string | undefined'。类型 'null' 不能分配给类型 'string | undefined'。 index.d.ts(2083, 9): 期望的类型来自于属性 'form',它在类型 'DetailedHTMLProps<ButtonHTMLAttributes, HTMLButtonElement>' 中声明。

考虑到此按钮的值应该是字符串,即表单本身的ID,我确实不太理解这个错误,也不理解其消息。

我的问题是,有人能解释一下为什么传递给此属性的值的类型可以是 nullHTMLFormElement 的原因是什么?对我来说这似乎没有太多意义。另外,如何在不禁用TypeScript的情况下修复此错误消息?

你可以在以下链接中找到带有此错误的代码沙箱:链接

英文:

Although in the MDN page of HTML button element there is an attribute of form that serves the purpose of connecting submit button to the form to which it belongs to (they do not need to be in the parent child hierarchy) TypeScript is giving me error when I create a button like this:

&lt;button	type=&#39;submit&#39; form=&#39;createCustomerForm&#39;&gt;

This is a full TS error message:

> TS2322: Type 'string | HTMLFormElement | null' is not assignable to type 'string | undefined'. Type 'null' is not assignable to type 'string | undefined'. index.d.ts(2083, 9): The expected type comes from property 'form' which is declared here on type 'DetailedHTMLProps<ButtonHTMLAttributes<HTMLButtonElement>, HTMLButtonElement>'

Considering that value of this button should be string, an id of the form itself, I do not understand really this error, nor its message.

My question is can someone explain what is the reason why the type of value passed to this attribute can be null or the HTMLFormElement. To me this does not make a lot of sense. Also, how to fix this error message without disabling ts?

You can find code sandbox with this error following this link

Redacted, but code with reproducible error is here:

import { MouseEventHandler, PropsWithChildren, ReactNode } from &quot;react&quot;;
import &quot;./styles.css&quot;;

type ButtonType = {
  inactive?: boolean;
  onClick?: MouseEventHandler&lt;HTMLButtonElement&gt; | undefined;
  text: string | ReactNode;
  type?: &quot;button&quot; | &quot;submit&quot; | &quot;reset&quot;;
} &amp; Partial&lt;HTMLButtonElement&gt;;

const Button = ({ inactive, text, type = &quot;button&quot;, ...rest }: ButtonType) =&gt; (
  &lt;button disabled={inactive} type={type} {...rest}&gt;
    {text}
  &lt;/button&gt;
);

const FormDialog = ({ children }: PropsWithChildren) =&gt; (
  &lt;dialog&gt;
    &lt;form id=&quot;createCustomerForm&quot;&gt;
      &lt;header&gt;
        &lt;h4&gt;Create customer&lt;/h4&gt;
        &lt;button autoFocus onClick={() =&gt; {}} type=&quot;button&quot;&gt;
          X
        &lt;/button&gt;
      &lt;/header&gt;
      &lt;div&gt;{children}&lt;/div&gt;
      &lt;footer&gt;
        &lt;div&gt;
          &lt;Button onClick={() =&gt; {}} text=&quot;close&quot; type=&quot;button&quot; /&gt;
        &lt;/div&gt;
        &lt;div&gt;
          &lt;Button form=&quot;createCustomerForm&quot; text=&quot;submit&quot; type=&quot;submit&quot; /&gt;
        &lt;/div&gt;
      &lt;/footer&gt;
    &lt;/form&gt;
  &lt;/dialog&gt;
);

export default function App() {
  return (
    &lt;FormDialog&gt;
      &lt;input type=&quot;text&quot; id=&quot;customerName&quot; /&gt;
    &lt;/FormDialog&gt;
  );
}

答案1

得分: 2

Here are the translated parts:

替代 Partial<HTMLButtonElement>,有两个选项:

  • React.ComponentPropsWithoutRef<'button'>

  • React.ButtonHTMLAttributes<HTMLButtonElement>

让我们看看 HTMLButtonElement 接口:

node_modules/typescript/lib/lib.dom.d.ts:

interface HTMLButtonElement extends HTMLElement {
    disabled: boolean;
    /** Retrieves a reference to the form that the object is embedded in. */
    readonly form: HTMLFormElement | null;
    // ...
}

HTMLButtonElement 接口提供了 HTMLButtonElement 的属性和方法,这是 DOM,而不是 HTML <button> 标签属性的接口。这就是为什么 form 属性是只读属性,其值是 HTMLFormElement

ButtonHTMLAttributes 接口提供了 <button> html 标签的属性(这是 React 中的内置组件)。

node_modules/@types/react/ts5.0/index.d.ts:

interface ButtonHTMLAttributes<T> extends HTMLAttributes<T> {
    disabled?: boolean | undefined;
    form?: string | undefined;
    //...
}

formstring 类型,其值是表单元素的 id。

英文:

Instead of Partial&lt;HTMLButtonElement&gt;, there are two options:

  • React.ComponentPropsWithoutRef&lt;&#39;button&#39;&gt;

  • React.ButtonHTMLAttributes&lt;HTMLButtonElement&gt;

type ButtonType = {
	inactive?: boolean;
	onClick?: MouseEventHandler&lt;HTMLButtonElement&gt; | undefined;
	text: string | ReactNode;
	type?: &#39;button&#39; | &#39;submit&#39; | &#39;reset&#39;;
} &amp; React.ComponentPropsWithoutRef&lt;&#39;button&#39;&gt;;

Or

type ButtonType = {
	inactive?: boolean;
	onClick?: MouseEventHandler&lt;HTMLButtonElement&gt; | undefined;
	text: string | ReactNode;
	type?: &#39;button&#39; | &#39;submit&#39; | &#39;reset&#39;;
} &amp; React.ButtonHTMLAttributes&lt;HTMLButtonElement&gt;;

codesandbox


Let's see the HTMLButtonElement interface:

node_modules/typescript/lib/lib.dom.d.ts:

interface HTMLButtonElement extends HTMLElement {
    disabled: boolean;
    /** Retrieves a reference to the form that the object is embedded in. */
    readonly form: HTMLFormElement | null;
    // ...
}

The HTMLButtonElement interface provides properties and methods for HTMLButtonElement, it's DOM, not the interface for HTML &lt;button&gt; tag's attributes. That's why the form property is a read-only property and its value is a HTMLFormElement

The ButtonHTMLAttributes interface provides the attributes for &lt;button&gt; html tag(a built-in component in React).

node_modules/@types/react/ts5.0/index.d.ts:

interface ButtonHTMLAttributes&lt;T&gt; extends HTMLAttributes&lt;T&gt; {
    disabled?: boolean | undefined;
    form?: string | undefined;
    //...
}

form is string type, its value is a form element's id.

huangapple
  • 本文由 发表于 2023年7月6日 17:59:56
  • 转载请务必保留本文链接:https://go.coder-hub.com/76627652.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定