在 TypeScript 中省略联合

Gol*_*den 7 types typescript

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

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

interface Y {
  abc: number;
  foo: number;
  baz: number;
}
Run Code Online (Sandbox Code Playgroud)

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

type Z = X | Y;
Run Code Online (Sandbox Code Playgroud)

结果类型是either X or Y,这很好。现在我使用以下方法删除公共字段之一Omit

type limitedZ = Omit<Z, 'foo'>;
Run Code Online (Sandbox Code Playgroud)

我期望的是limitedZ具有以下形式:

{ abc: number, bar: number } | { abc: number, baz: number }
Run Code Online (Sandbox Code Playgroud)

相反,独立的字段消失了,剩下的就是abc双方共享的字段。这是为什么?

这是一个演示链接

ome*_*ell 3

为了使用联合来完成你想要的事情,你可以这样做 - 但它没有做你所期望的

type limitedZ = Omit<X, 'foo'> | Omit<Y, 'foo'>

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

我假设当您调用Omit<Z, 'foo'>typescript 时,会创建一个由两种类型的公共键(即 abc 和 foo)形成的类型,然后删除 foo,这样就只剩下 abc 了。

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

type ThirdType = X & Y

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

type FourthType = Omit<ThirdType, 'foo'>

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

type limitedZ = Omit<X & Y, 'foo'>

这有助于解释发生的事情吗?