如何在分配的函数可能未定义时声明一个 onChange()。

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

How to declare a onChange() when the assigned funcion can be undefined

问题

I'm new with Typescript and JavaScript and I'm not sure how to solve a situation on my React project.
我是Typescript和JavaScript的新手,不确定如何解决我的React项目中的一个情况。

I have this component below, but my onChange() line is not compiling. I receive a message saying this:
我有下面这个组件,但是我的 onChange() 行不会编译。我收到了以下消息:

Type '((value: boolean) => void) | undefined' is not assignable to type '(value: boolean) => void'.
  Type 'undefined' is not assignable to type '(value: boolean) => void'.ts(2322)
ISelectUnselectAll.ts(3, 3): The expected type comes from property 'onChange' which is declared here on type 'IntrinsicAttributes & ISelectUnselectAll'
<SelectUnselectAll
  value={selectUnselectAll}
  disabled={!totalsStore.parsedList.length}
  onChange={onSelectUnselectAll}
  mode={'MENU'}
/>

Actually I think the problem is because my onSelectUnselectAll function is coming by props from an interface when this function is optional. But I don't know how to solve it.
实际上,我认为问题是因为我的 onSelectUnselectAll 函数是从一个接口的 props 中传递过来的,而这个函数是可选的。但我不知道如何解决它。

export interface IExtraButtonsHeaderInvoiceTotals {
  onSelectUnselectAll?: (value: boolean) => void;

If I remove the ? the code compiles fine, but I can't remove the ?.
如果我移除 ?,代码就能成功编译,但我不能移除 ?

I appreciate any help.
我感谢任何帮助。

英文:

I'm new with Typescript and JavaScript and I'm not sure how to solve a situation on my React project.
I have this component below, but my onChange() line is not compiling. I receive a message saying this:

Type &#39;((value: boolean) =&gt; void) | undefined&#39; is not assignable to type &#39;(value: boolean) =&gt; void&#39;.
  Type &#39;undefined&#39; is not assignable to type &#39;(value: boolean) =&gt; void&#39;.ts(2322)
ISelectUnselectAll.ts(3, 3): The expected type comes from property &#39;onChange&#39; which is declared here on type &#39;IntrinsicAttributes &amp; ISelectUnselectAll&#39;
&lt;SelectUnselectAll
  value={selectUnselectAll}
  disabled={!totalsStore.parsedList.length}
  onChange={onSelectUnselectAll}
  mode={&#39;MENU&#39;}
/&gt;}

Actually I think the problem is because my onSelectUnselectAll function is coming by props from an interface when this function is optional. But I don't know how to solve it.

export interface IExtraButtonsHeaderInvoiceTotals {
  onSelectUnselectAll?: (value: boolean) =&gt; void;

If I remove the ? the code compiles fine, but I can't remove the ?.

I appreciate any help

答案1

得分: 0

Typescript的目的是帮助代码维护并预防应用中可能发生的错误,这就是为什么会出现错误提示。ISelectUnselectAll是一个契约,确切地规定了你可以传递给组件的内容,在这种情况下,该契约表示onChange 不能 是未定义的,无论出于什么原因。

当你在参数中添加?时,它变得可能是未定义的,正如你所看到的错误提示中写着((value: boolean) => void) | undefined) 无法分配给 (value: boolean) => void,这意味着ISelectUnselectAll的参数onChange应始终被定义。

为了解决这个问题,你可以在执行之前验证参数是否存在,或者移除?使其成为一个强制参数,并确保onSelectUnselectAll始终是一个函数。

const handleSelectUnselect = () => {
    if (onSelectUnselectAll) {
        onSelectUnselectAll()
    }
}

<SelectUnselectAll
   value={selectUnselectAll}
   disabled={!totalsStore.parsedList.length}
   onChange={handleSelectUnselect}
   mode={'MENU'}
/>

此外,如果你的ESlint规则允许,你还可以简单地添加一个三元条件:

onChange={onSelectUnselectAll ?? onSelectUnselectAll()} 

另外,你还可以更改ISelectUnselectAll接口,让onChange为未定义的情况:

interface ISelectUnselectAll {
   onChange: ((value: boolean) => void) | undefined;
}
英文:

Typescript purpose is to help with code maintenance and also to prevent possible errors that could happen in your application, that's why that error pops up, ISelectUnselectAll is a contract which dictates exactly what you can pass to a your component, in that case, that contract says, onChange cannot be undefined, for whatever reason.

When you add ? to a parameter it becomes possibly undefined and as you can see, the error says ((value: boolean) =&gt; void) | undefined) is not assignable to (value: boolean) =&gt; void, that means that the ISelectUnselectAll parameter onChange should always be defined.

To solve this you could verify if the parameter exists before executing it, or remove ? making it a obligatory param and making sure that onSelectUnselectAll always is a function.

const handleSelectUnselect = () =&gt; {
    if(onSelectUnselectAll) {
       onSelectUnselectAll()
    }
} 

&lt;SelectUnselectAll
   value={selectUnselectAll}
   disabled={!totalsStore.parsedList.length}
   onChange={handleSelectUnselect}
   mode={&#39;MENU&#39;}
/&gt;

Also, you can simply add a ternary if, if your ESlint rules allow it:

onChange={onSelectUnselectAll ?? onSelectUnselectAll()} 

Also you could change the interface ISelectUnselectAll and let onChange be undefined

interface ISelectUnselectAll {
   onChange: ((value: boolean) =&gt; void) | undefined)
}

答案2

得分: 0

You should decide what to do when it is undefined, and handle that case.

也许原始接口的意图是,如果没有提供函数,则什么都不会发生,在这种情况下,以下应该是正确的。如果定义了函数,则传递函数,否则将其替换为什么都不做的默认函数。

<SelectUnselectAll
value={selectUnselectAll}
disabled={!totalsStore.parsedList.length}
onChange={onSelectUnselectAll ?? () => {}}
mode={'MENU'}
/>

这里有一个可工作的示例。

您应该考虑的另一种选择是,让默认函数记录错误或抛出异常。

英文:

You should decide what to do when it is undefined, and handle that case.

Maybe the intent behind the original interface is that, if no function is provided, nothing is done, in which case the following should be correct. Here the function is passed if defined, and otherwise it is replaced by a default that does nothing.

&lt;SelectUnselectAll
  value={selectUnselectAll}
  disabled={!totalsStore.parsedList.length}
  onChange={onSelectUnselectAll ?? () =&gt; {}}
  mode={&#39;MENU&#39;}
/&gt;

Here is a working example.

An alternative you should consider would be to have the default function log an error or throw an exception.

答案3

得分: 0

谢谢,大家。

最简单的解决方案是在渲染组件之前检查我的函数是否已定义。
代码如下:

{onSelectUnselectAll &&
    <SelectUnselectAll
        value={selectUnselectAll}
        disabled={!totalsStore.parsedList.length}
        onChange={onSelectUnselectAll}
        mode={'MENU'}
     />
}

现在它运行正常。

英文:

Thanks, guys.

The simplest solution was to check if my function is defined before rendering the component.
The code looked like this:

{onSelectUnselectAll &amp;&amp;
    &lt;SelectUnselectAll
        value={selectUnselectAll}
        disabled={!totalsStore.parsedList.length}
        onChange={onSelectUnselectAll}
        mode={&#39;MENU&#39;}
     /&gt;
}

It's working fine now.

huangapple
  • 本文由 发表于 2023年6月29日 22:31:31
  • 转载请务必保留本文链接:https://go.coder-hub.com/76582054.html
匿名

发表评论

匿名网友

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

确定