英文:
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 '((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.
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
答案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) => void) | undefined)
is not assignable to (value: boolean) => 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 = () => {
if(onSelectUnselectAll) {
onSelectUnselectAll()
}
}
<SelectUnselectAll
value={selectUnselectAll}
disabled={!totalsStore.parsedList.length}
onChange={handleSelectUnselect}
mode={'MENU'}
/>
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) => 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.
<SelectUnselectAll
value={selectUnselectAll}
disabled={!totalsStore.parsedList.length}
onChange={onSelectUnselectAll ?? () => {}}
mode={'MENU'}
/>
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 &&
<SelectUnselectAll
value={selectUnselectAll}
disabled={!totalsStore.parsedList.length}
onChange={onSelectUnselectAll}
mode={'MENU'}
/>
}
It's working fine now.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论