我正在尝试定义一个事件处理程序,可用于主要共享 event.target 结构的不同组件:
import { SelectChangeEvent } from '@mui/material'
const handleValueChange = ({ target }: ChangeEvent<HTMLInputElement> | SelectChangeEvent) => {
const { name, value, type, checked } = target
setState({
[name]: type === 'checkbox' ? checked : value
})
}
我遇到的问题是类型type
上checked
不存在SelectChangeEvent
:
Property 'checked' does not exist on type '(EventTarget & { value: string; name: string; }) | (EventTarget & HTMLInputElement)'.
我真的不想仅仅因为类型差异而复制代码并创建另一个处理程序。我可以在代码中确保当我调用这个处理程序时它实际上将具有所需的属性,但是我如何告诉 Typescript 呢?
如果我的方法不正确,我应该如何重构它以使其不重复工作(如果可能)?
谢谢
您可以使用类型断言来做到这一点,如下所示:
const handleValueChange = ({ currentTarget }: ChangeEvent<HTMLInputElement> | SelectChangeEvent) => {
const { name, type, value, checked } = currentTarget as HTMLInputElement;
setState({
[name]: type === "input" ? checked : value
});
};
...最好尽可能避免类型断言。(游乐场链接。)例如,在上面,您知道当它与元素一起使用时您会得到undefined
。它仍然有效,因为它不是一个元素,所以你最终会使用而不是,但最好在除了非常有限的情况下避免它。考虑到函数的类型,上述内容可能对许多人来说已经足够有限了。type
select
type
"input"
select
value
checked
相反,为了更严格,您可以使用一两个类型保护来缩小 的类型currentTarget
(通常比 更好的选择target
),以保证类型信息与运行时的实际情况相匹配。
我们可以从instanceof
检查开始:
const handleValueChange = ({ currentTarget }: ChangeEvent<HTMLInputElement> | SelectChangeEvent) => {
let value: string | boolean;
if (currentTarget instanceof HTMLInputElement) {
value = currentTarget.checked;
} else {
value = currentTarget.value; // <== But we still have errors here
}
const { name } = currentTarget; // <== and one here
setState({
[name]: value
});
};
错误是因为currentTarget
可能是null
,并且在else
分支中,只是 type EventTarget
。
instanceof
我们可以通过第二次检查和 a来解决这个问题throw
:
const handleValueChange = ({ currentTarget }: ChangeEvent<HTMLInputElement> | SelectChangeEvent) => {
let value: string | boolean;
if (currentTarget instanceof HTMLInputElement) {
value = currentTarget.checked;
} else if (currentTarget instanceof HTMLSelectElement) {
value = currentTarget.value;
} else {
throw new Error(`Expected an HTMLInputElement or HTMLSelectElement`);
}
const { name } = currentTarget;
setState({
[name]: value
});
};
本文收集自互联网,转载请注明来源。
如有侵权,请联系 [email protected] 删除。
我来说两句