【问题标题】:Typescript Omit<> does not show error when spreading object with omitted attributeTypescript Omit<> 在传播具有省略属性的对象时不显示错误
【发布时间】:2023-02-22 03:33:50
【问题描述】:

为什么 TypeScript 看不到我正在尝试传播具有不属于 Baby 类型属性的 Human 类型的对象?这不仅适用于这个例子,它适用于任何对象是属性的超集。对于不显示错误的 TS 来说,拥有该类型的所有属性就足够了,但您可以传递比您需要的更多的属性。为什么?如果我可以将任何超集对象传递给它,类型有什么意义..

我真的必须手动从上层对象中选择属性以确保我不会传递超过我需要的属性吗? 想象一下,如果我省略 100 个属性并展开对象,并且仍然在内存中获取所有这些属性。这打败了我的类型的目的

interface Human {
  name: string;
  surname: string;
  age: number;
}
const human1: Human = {
  name: "Chad",
  surname: "Lingovski",
  age: 26,
};
type Baby = Omit<Human, "age">;
const baby1: Baby = { ...human1 }; //this is allowed, why?
const baby2: Baby = { name: "Chad", surname: "Lingovski", age: 26 }; //this is not allowed

我希望 TS 显示错误。它不允许我访问年龄属性,但我可以控制台记录整个对象和年龄。

【问题讨论】:

  • 因为打字稿只会阻止您添加不存在的文字键。 Baby 仍可分配给 Human
  • 因为Human 拥有Baby 需要的所有属性
  • 我的问题是,如果我明确说明我的类型需要什么,为什么我可以将 Human 分配给 Baby。我不需要更多,我需要的正是我写的

标签: javascript typescript javascript-objects


【解决方案1】:

TypeScript 允许将 Human 类型的对象传播到 Baby 类型的对象上,因为传播运算符是浅拷贝。它从源对象复制所有属性及其值,但不复制对象的原型、方法或符号。

在这种情况下,human1 对象具有 Baby 对象所具有的所有属性,外加一个额外的 age 属性。当您将 human1 对象扩展到 Baby 对象时,TypeScript 会创建一个具有与 human1 相同属性但没有 age 属性的新对象。这是因为 Baby 类型指定它没有 age 属性,而 TypeScript 使用该信息来验证展开操作。

虽然确实可以将超集对象传递给子集类型,但通常不建议这样做。在 TypeScript 中使用类型的目的是提供更好的类型安全并在编译时捕获错误。在这种情况下,如果您要向 Human 类型添加一个新属性,展开操作仍然有效,但生成的对象将具有 Baby 类型不允许的附加属性。这可能会导致代码中出现意外行为和错误。

【讨论】:

    【解决方案2】:

    展开带有省略属性的对象时 TypeScript 不显示错误的原因是因为 JavaScript 中的展开运算符在编译时不执行类型检查。扩展运算符只是将一个对象或数组扩展为单独的属性,开发人员需要确保生成的对象或数组符合预期的类型。

    当您使用 Omit 实用程序类型时,TypeScript 会创建一个新类型,它是原始类型的副本,但删除了指定的属性。在您的示例中,Baby 类型是不包含 age 属性的 Human 类型的子集。

    当您将 human1 对象扩展到 baby1 对象时,TypeScript 会发现 human1 的所有属性都存在于 Baby 中,因此它允许扩展操作继续进行而不会出现错误。但是,如果您尝试将 age 属性直接分配给 baby2,TypeScript 将正确显示错误,因为 Baby 类型不包含 age 属性。

    为确保只将必需的属性传递给 Baby 类型,您可以使用 Pick 实用程序类型手动选择属性。例如:

    type Baby = Pick<Human, "name" | "surname">;
    

    这将创建一个新类型,它只包含 Humannamesurname 属性,可以安全地分配给 baby1

    【讨论】:

      猜你喜欢
      • 2019-05-16
      • 1970-01-01
      • 1970-01-01
      • 2020-05-04
      • 1970-01-01
      • 2021-07-06
      • 2019-03-28
      • 2014-03-11
      • 2019-10-02
      相关资源
      最近更新 更多