Typescript 对象属性取决于类型

维陶塔斯·布特库斯

我正在尝试定义一个事件处理程序,可用于主要共享 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
  })
}

我遇到的问题是类型typechecked不存在SelectChangeEvent

Property 'checked' does not exist on type '(EventTarget & { value: string; name: string; }) | (EventTarget & HTMLInputElement)'.

我真的不想仅仅因为类型差异而复制代码并创建另一个处理程序。我可以在代码中确保当我调用这个处理程序时它实际上将具有所需的属性,但是我如何告诉 Typescript 呢?

如果我的方法不正确,我应该如何重构它以使其不重复工作(如果可能)?

谢谢

TJ克劳德

可以使用类型断言来做到这一点,如下所示:

const handleValueChange = ({ currentTarget }: ChangeEvent<HTMLInputElement> | SelectChangeEvent) => {
    const { name, type, value, checked } = currentTarget as HTMLInputElement;
    setState({
        [name]: type === "input" ? checked : value
    });
};

...最好尽可能避免类型断言。游乐场链接。)例如,在上面,您知道当它与元素一起使用时您会得到undefined它仍然有效,因为它不是一个元素,所以你最终会使用而不是,但最好在除了非常有限的情况下避免它。考虑到函数的类型,上述内容可能对许多人来说已经足够有限了。typeselecttype"input"selectvaluechecked

相反,为了更严格,您可以使用一两个类型保护来缩小 的类型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] 删除。

编辑于
0

我来说两句

0 条评论
登录 后参与评论

相关文章

TypeScript:接口,取决于(递归)属性的类型

Typescript返回类型取决于对象参数

Typescript返回类型取决于参数

Typescript函数的返回类型取决于参数的数量或类型

Typescript通用约束,其中一种类型的属性取决于另一种类型

Typescript接口的可选属性,取决于其他属性

Typescript对象属性类型

有一个方法的泛型类型取决于 TypeScript 中类的泛型类型

Typescript:创建一个方法,返回的类型取决于类

动态方法重载取决于 TypeScript 中的枚举(可索引的方法签名而不是属性)

值类型取决于键类型的对象

动态访问对象属性的Typescript类型推断

对象属性路径的 TypeScript 类型定义

TypeScript 不能正确推断对象属性的类型

Typescript 动态联合类型的动态对象属性

从 Typescript 中的属性值推断对象的类型

Typescript数组对象属性值作为类型

Arangodb更新属性取决于边缘类型

sizeof(pointer)是否取决于对象类型?

交换链接类型取决于模型对象

取消绑定取决于对象类型

Typescript - 基于对象联合属性类型的通用返回类型

具有包含特定类型的对象属性的TypeScript类型

根据Typescript中多个对象的同名属性创建对象类型?

TypeScript对象类型

Typescript回调参数取决于其他选项参数

如何使用条件类型分配使类型取决于属性值

Typescript是对象属性的Type

DataTemplate绑定取决于属性类型和工作属性Binding