考虑类型FooBar1和FooBar2定义如下:
type Foo = { foo: string };
type Bar = { bar: number };
type FooBar1 = Foo & Bar;
type FooBar2 = { foo: string; bar: number };
Run Code Online (Sandbox Code Playgroud)
FooBar1和 和有FooBar2什么不一样?我的尝试/研究:
tsd-请参阅此处)tsd-请参阅此处){ foo } & { bar }自动进入{ foo, bar },而它倒塌了其他复杂类型简单的形式,如NonNullable<string | undefined>以string:// |------------------------------------------------------------|
// | let x: { |
// | a: string; |
// | } & { |
// | b: string; |
// | } |
// | -----------------------------------------------------------|
// ^
// | When hovering `x` here:
// |
let x: { a: string } & { b: string };
Run Code Online (Sandbox Code Playgroud)
编辑: TypeScript 中扩展接口和交叉接口的区别?已被建议为重复,但我不同意。我不是将交集与接口的扩展进行比较,而是将交集与另一种原始类型进行比较,不涉及接口或扩展。
在你的例子中,我们可以说 和FooBar1是FooBar2相等的。我们确实可以证明:
type Equals<A, B> =
A extends B
? B extends A
? true
: false
: false
type test0 = Equals<{a: 1} & {b: 2}, {a: 1, b: 2}> // true
Run Code Online (Sandbox Code Playgroud)
但对于一般性的答案,我们只能说它们并不总是相等。为什么?因为在某些情况下交叉点可以解析为never。如果 ts 发现交集有效,则继续处理,否则返回never。
import {O} from "ts-toolbelt"
type O1 = {a: 1, b: 2}
type O2 = {a: 1} & {b: 2} // intersects properly
type O3 = {a: 1, b: 2} & {b: 3} // resolved to `never`
type test0 = Equals<O1, O2>
// true
type test1 = O.Merge<{a: 1, b: 2}, {b: 3, c: 4}>
// {a: 1, b: 2, c: 4}
Run Code Online (Sandbox Code Playgroud)
这里类型O3解析为never因为bis3并且它不能与 重叠2。让我们更改我们的示例,以表明如果您具有以下条件,则交叉点将起作用:
import {A} from "ts-toolbelt"
type O4 = A.Compute<{a: 1, b: number} & {b: 2}> // {a: 1, b: 2}
type O5 = A.Compute<{a: 1, b: 2} & {b: number}> // {a: 1, b: 2}
Run Code Online (Sandbox Code Playgroud)
这个例子还强调了交叉点的工作原理——就像并集交叉点一样。TypeScript 将遍历所有属性类型并将它们相交。我们强制 TypeScript 计算与 的交集结果A.Compute。
简而言之,如果 ts 不能与所有成员重叠,则该交集的乘积为never。因此,它可能不适合作为合并工具:
type O3 = {a: 1, b: 2} & {b: 3} // resolved to `never`
Run Code Online (Sandbox Code Playgroud)
所以记住,&它不是一个合并工具。仅当它们具有不重叠的键时才A & B等于。{...A, ...B}如果您需要合并类型,请使用O.Merge.
| 归档时间: |
|
| 查看次数: |
511 次 |
| 最近记录: |