为什么Typescript交集只在对象上表现为并集?

为什么Typescript交集只在对象上表现为并集?,typescript,Typescript,基本体的交集 type foo = number; type bar = boolean; type baz = foo & bar; type foo = { fizz: number }; type bar = { fuzz: boolean }; type baz = foo & bar; 与福和巴没有交叉口。 因此,baz类型是never 很好,这很有道理 对象的交点 type foo = number; type bar = boolean;

基本体的交集

type foo = number;
type bar = boolean;

type baz = foo & bar;
type foo = {
    fizz: number
};

type bar = {
    fuzz: boolean
};

type baz = foo & bar;
与福和巴没有交叉口。 因此,
baz
类型是
never

很好,这很有道理

对象的交点

type foo = number;
type bar = boolean;

type baz = foo & bar;
type foo = {
    fizz: number
};

type bar = {
    fuzz: boolean
};

type baz = foo & bar;
foo
bar
中没有相交的属性。 就像在基本交点示例中一样

但该类型不是
never
类型,而是强制类型为
baz
的对象具有
baz
bar
的所有属性的组合

例如:

type foo = {
    fizz: number
};

type bar = {
    fuzz: boolean
};

type baz = foo & bar;


// FAILS
const o: baz = {
    fuzz: true
}

// FAILS
const o: baz = {
    fizz: 1,
}

// PASSES
const o: baz = {
    fizz: 1,
    fuzz: true
}

重述一下: 在原语示例中,foo和bar的交集没有任何内容。因此,它的类型从来都不是

对象示例中foo和bar的交集没有任何内容。然而,它的类型更像是一个并集而不是交叉点。i、 e.
baz
类型的对象需要
foo
bar
的属性

问题

在原语示例中,其行为类似于交点。但在对象示例中,它的行为与交叉点不同。为什么这些行为不一致

为什么对象的交集表现为并集,而基本体的交集表现为正确的交集

为什么对象的交集表现为并集,而基本体的交集表现为正确的交集

它不是物体的交叉点。这是一个类型的交叉点。类型的交集将生成一个新类型,该类型具有其所有属性,而不是其公共属性

类型交叉口与集合交叉口不同,集合交叉口是您绊倒的地方


另一个困惑是,您试图进行基本体(字符串、数字)的交集。这在技术上是不正确的,但TypeScript的设计包括在创建类型时从不出错。因此,他们的解决方案是让原语类型的交集解析为
从不
,而不是编译时错误。

没有类型为
number&boolean
的值,但也有类型为
{fizz:number}&{fuzz:number}
的值。行为是一贯的。在这两种情况下,它的行为都像一个交集。这就是相交对象类型的含义。猫有爪子,苹果有柄,所以如果某个东西是猫和苹果,那么它必须有爪子和柄。如果它是一个联盟(一只猫或一个苹果),那么它不一定有爪子,也不一定有柄。如果它真的像一个联盟
foo | bar
,那么你的两个失败的例子——分别分配给
foo
bar
——就不会是失败的例子,他们将被接受为工会类型的成员。同样相关:请参阅。TypeScript中的对象类型是开放/可扩展的;它们必须包含声明的属性,但也可能包含未声明的属性。类型为
{fizz:number}
的值必须具有类型为
number
fizz
属性,但不要求它仅具有
fizz
属性。值
{fizz:1,fuzz:2}
是有效的
{fizz:number}
。因此,找到一个类型的值是绝对可能的,它既是
{fizz:number}
又是
{fuzz:number}
。。。这两种类型的交集。类型交集可视为集合交集-可分配给类型
A&B
的值集合等于可分配给
A
的值集合,与可分配给
B
的值集合相交@kaya3您描述的“集合交集”是集合的并集,不是集合的交集。集合交集是属于两者的项的集合,而集合并集是属于两者的项的集合。(类型交集不同)如果你说的是真的,那么如果
类型A={foo:number}
类型B={bar:number}
,那么
A&B
将是
{}
,因为可分配给A的所有值集和可分配给B的所有值集的交集intersected是空集。这就是为什么我指出类型交叉点与集合交叉点不同。不,它是集合交叉点。例如,对象
{fizz:1,fuzz:'nota boolean'}
可分配给
foo
,但不能分配给
bar
,因此它不在交集类型
foo&bar
中。您谈论的是在类型上声明的属性集,但我谈论的是可分配给该类型的值集。可分配给
foo
bar
的值集绝对不是空的;例如,它包含对象
{fizz:1,fuzz:true}