【问题标题】:Omit on unions in TypeScript在 TypeScript 中省略联合
【发布时间】:2021-01-22 01:13:18
【问题描述】:

假设我有两个接口,XY,它们共享一些字段,但也有独立的字段:

interface X {
  abc: number;
  foo: number;
  bar: number;
}

interface Y {
  abc: number;
  foo: number;
  baz: number;
}

现在我创建了这些类型的联合:

type Z = X | Y;

结果类型是either X or Y,这很好。现在我使用Omit 删除其中一个常用字段:

type limitedZ = Omit<Z, 'foo'>;

我希望limitedZ 具有以下形式:

{ abc: number, bar: number } | { abc: number, baz: number }

取而代之的是,独立的字段消失了,剩下的就是两者共享的abc 字段。这是为什么呢?

这是demo link

【问题讨论】:

  • 很奇怪。如果我这样做 const x: limitedZ = {abc: 1, bar: 1, baz: 1}; 错误消息是:“Type '{ abc: number; bar: number; baz: number; }' is notassignable to type 'Pick ”。这向我表明Omit 是根据Pick 定义的,这反过来会导致联合类型出现问题,因为您不能声称limitedZ 具有 barbaz财产。可能是因为它适用于 {abc: number; foo: number;} 的组合结果,它至少具有 barbaz 之一,但也是可选的。
  • 您可能可以在这里找到一些答案:stackoverflow.com/questions/57103834/…
  • “结果类型是 X 或 Y” - 这并不完全正确。它是“X 或 Y 或两者”(包括 OR),而 XOR 将是可区分的联合类型。至于为什么部分:keyof,是Omit的一部分,只有returns all common properties

标签: typescript types


【解决方案1】:

为了使用联合来完成您想要的事情,您可以这样做 - 但它并没有达到您的预期

type limitedZ = Omit&lt;X, 'foo'&gt; | Omit&lt;Y, 'foo'&gt;

由管道表示的联合几乎是一个 XOR,因此结果的类型必须是一个或另一个,所以 X 或 Y,或者两种类型共有的键(所以不是真正的 xor)。这就是为什么你会得到意想不到的输出。如果您想简单地从这两种类型中删除 foo ,这将起作用,但它不会创建 X 和 Y 的键合并的类型(看起来)。 This 会比我解释得更好。

我假设当您调用 Omit&lt;Z, 'foo'&gt; 时,typescript 会创建一个由两种类型的公共键组成的类型,例如 abc 和 foo,然后您删除 foo,因此只剩下 abc。

如果您想创建一个具有 x 键和 y 键的类型 - 您需要执行类似的操作来创建交集类型。

type ThirdType = X &amp; Y

这种类型现在具有 X 的所有键和 Y 的所有键。然后您可以限制它以删除 foo - 我认为这是您想要做的。

type FourthType = Omit&lt;ThirdType, 'foo'&gt;

或者在一行中完成所有操作

type limitedZ = Omit&lt;X &amp; Y, 'foo'&gt;

这是否有助于解释发生了什么?

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-07-06
    • 2020-09-12
    • 1970-01-01
    • 2019-05-26
    • 1970-01-01
    相关资源
    最近更新 更多