我注意到在Type脚本中使用useState时出现了意外的行为,它允许分配任何属性,即使该属性不存在于接口中.例如:

interface ComponentState {
    foo: string,
    bar: boolean
}

const [state, setState] = useState<ComponentState>({ foo: 'foo', bar: false });

const onAction = () => {
    setState((prevState) => {
        ...prevState,
        bar: true,
        help: 'why is this allowed?'
    });
}

为什么TypeScrip没有抱怨"Help"属性?如果我试图将bar(布尔值)设置为字符串,它将会出错.

这与PrevState对象传播有关吗?

我不喜欢这样,因为它允许错误通过.我是不是遗漏了什么?我查看了useState的定义,但我不认为它允许[key: string]: any

推荐答案

这不是特定的react ,而是一个打字笔迹structural typing system的艺术品.

简而言之,在许多情况下,类型脚本允许额外的属性,因为从setState()函数返回的对象仍然满足ComponentState,即使它有额外的属性.

一方面,这通常很好,并不会真正影响行为,因为代码中其他地方的逻辑不允许访问额外的属性,它们是一种无论如何都不能访问的幻影属性--TypeScrip不允许这样做,因为它们不是ComponentState定义的一部分.我们通常更关心的是确保对象上具有我们期望和需要的正确属性,而不是拥有不需要的额外属性.

另一方面,这不一定是可取的,因为您可能会意外地在某个地方添加额外的属性,以为它们将在其他地方可见/可用,尽管它们不是可见的,或者会出错,因为其他逻辑读取属性而不期望额外的属性.例如,假设确切的属性是已知的,但事实证明还有其他属性,那么在某个地方使用Object.keys()又会怎样呢?

解决这一问题的一种方法是使用更显式的类型定义,这些定义通常不是必需的,但在这里可能更有用.例如:

function MyComponent() {
  const [state, setState] = React.useState<ComponentState>({ foo: 'foo', bar: false });

  const onAction = () => {
    setState((prevState) => {
      const result: ComponentState = {
        ...prevState,
        bar: true,
        help: 'why is this allowed?'
      };

      return result;
    });
  }
}

当您try 定义result时,这将正确地给出一个错误.

用这种方法得到错误的原因是因为excess property checking,而不是直接返回类型.只有在某些情况下,TypeScrip才会执行此操作:

在将对象文字赋给其他变量或作为参数传递时,对象文字会得到特殊处理,并接受额外的属性判断.

Typescript相关问答推荐

为什么TypScript对条件函数类型和仅具有条件返回类型的相同函数类型的处理方式不同?

Typescript问题和缩减器状态不会在单击时添加用途.属性'状态和调度'不存在于userContextType类型上'|null'

如果存在ts—mock—imports,我们是否需要typescpt中的IoC容器

Angular 信号:当输入信号改变值时,S触发取数的正确方式是什么?

在TypeScrip的数组中判断模式类型

类型脚本返回的类型包含无意义的泛型类型名称

为什么有条件渲染会导致material 自动完成中出现奇怪的动画?

从TypeScrip中的其他类型检索泛型类型

Angular 17子路由

有没有办法在Zod中使用跨字段验证来判断其他字段,然后呈现条件

创建依赖函数参数的类型

使用Type脚本更新对象属性

VITEST警告:当前的测试运行器不支持After Each/teardown挂钩

如何正确地将元组表格输入到对象数组实用函数(如ZIP)中,避免在TypeScrip 5.2.2中合并所有值

如何在具有嵌套数组的接口中允许新属性

内联类型断言的工作原理类似于TypeScrip中的断言函数?

可以用任意类型实例化,该类型可能与

Typescript不允许在数组中使用联合类型

Svelte+EsBuild+Deno-未捕获类型错误:无法读取未定义的属性(读取';$$';)

如何在Vuetify 3中导入TypeScript类型?