Typescript:了解并集和交集类型

ou6hu8tu  于 2023-03-04  发布在  TypeScript
关注(0)|答案(5)|浏览(194)

我试图对 typescript 中的Union和Intersection类型有一种直觉,但我无法理解这种情况:Playground链接

interface A {
    a: number;
}

interface B{
    b: boolean;
}


type UnionCombinedType = A | B;
type IntersectionType = A & B;

const obj: UnionCombinedType = {
    a: 6,
    b: true,
}

const obj2: IntersectionType = {
    a: 6,
    b: true,
}

为什么允许我把两个值都放在交集类型中?两个接口之间的交集是空的。如果我把&读为AND,那么我就很清楚为什么它允许我添加两个属性。但是我应该把|关键字读为OR,并且我希望它只允许我赋值ab,而不是两者都赋值。
有人能给我一些关于这些类型的直觉吗?

ryoqjall

ryoqjall1#

鉴于以下情况:

interface A {
    a: number;
    c: number;
}

interface B{
    b: boolean;
    c: number;
}

联合类型A | B的表达式可赋给AB。它必须具有AB(或两者)中的属性

const oA: A | B = {
    a: 6,
    c: 6
}

const oB: A | B = {
    b: true,
    c: 6
}

const oC: A | B = {
    a: 6,
    b: true
    c: 6
}

但是像A | B这样的类型有什么操作呢?只有那些同时属于AB的操作

oA.c = 1; // valid

交点类型A & B,如果它可分配给A和B(因此必须同时具有A和B的特性)。

const obj: A & B = {
    a: 6,
    b: true,
    c: 1
}
    • 更新**

你问"为什么你例子中的A和B可以取b prop?它不能赋值给类型A"
这显然不是真的。任何具有A的所有属性的类型都可以赋给A。额外的属性没有害处:

const aAndExtraProp = {
  a: 6,
  d: 6
};

const ca0: A = aAndExtraProp;

您可能会对对象文本的多余属性检查感到困惑:
对象文字会得到特殊的处理,当把它们赋给其他变量或作为参数传递时,会进行额外的属性检查。如果对象文字有任何"目标类型"没有的属性,你会得到一个错误:

const ca1: A = {
  a: 6,
  d: 6 //ERROR
};
rseugnpd

rseugnpd2#

从联合类型接受什么的Angular 来考虑。可以赋给字符串的一组内容|数字字段是所有字符串的集合和所有数字的集合的并集。可以赋给字符串&数字的事物的集合是空的,因为所有字符串的集合和所有数字的集合没有重叠。
我认为你把它想象成域上的集合运算符,而不是每种类型所代表的集合的集合运算符。
////////////////////////
这是数学术语:"类型"是其所有可能值的集合,例如boolean = {true,false};现在,类型T和U的并集是由T或U中的值组成的集合(即,T与U合并);类似地,T和U中的值的交集(即它们的公共部分)。
成员是可访问的当且仅当它位于所有可能的值上。对于联合,类型T的值|U可能是T,也可能是U,我们不知道哪一个是合法的,所以只有公共属性是合法的,正如你所看到的,对类型的操作意味着对成员的不同但互补的操作,这是德摩根定律的结果。
https://www.reddit.com/r/typescript/comments/9qduq3/why_is_type_intersection_called_like_that_its/

u0sqgete

u0sqgete3#

以下示例可能有助于您理解TS联合和交叉的工作方式:

interface A {
  a1: string,
  a2: string,
}

interface B {
  b1: string,
  b2: string;
}

type UnionAB = A | B;
type IntersectionAB = A & B;

const unionAB1: UnionAB = {
  a1: 'xxx',
  a2: 'xxx',
  b1: 'xxx',
  b2: 'xxx',
};

const unionAB2: UnionAB = {
  a1: 'xxx',
  a2: 'xxx',
};

const unionAB3: UnionAB = {
  b1: 'xxx',
  b2: 'xxx',
};

// Error
// Property 'a1' does not exist on type 'B'.
console.log(unionAB3.a1);

const unionAB4: UnionAB = {
  a1: 'xxx',
  a2: 'xxx',
  b2: 'xxx',
};

// Error
// Property 'b1' does not exist on type 'UnionAB'.
// Property 'b1' does not exist on type 'A'.
console.log(unionAB4.b1);

// Error
// Type '{ a1: string; b2: string; }' is not assignable to type 'UnionAB'.
// Property 'b1' is missing in type '{ a1: string; b2: string; }' but required in type 'B'.
const unionAB5: UnionAB = {
  a1: 'xxx',
  b2: 'xxx',
};

const intersectionAB1 : IntersectionAB = {
  a1: 'xxx',
  a2: 'xxx',
  b1: 'xxx',
  b2: 'xxx',
};

// Error
// Type '{ a1: string; a2: string; b1: string; }' is not assignable to type 'IntersectionAB'.
// Property 'b2' is missing in type '{ a1: string; a2: string; b1: string; }' but required in type 'B'.
const intersectionAB2 : IntersectionAB = {
  a1: 'xxx',
  a2: 'xxx',
  b1: 'xxx',
};

// Error
// Type '{ a2: string; b1: string; b2: string; }' is not assignable to type 'IntersectionAB'.
// Property 'a1' is missing in type '{ a2: string; b1: string; b2: string; }' but required in type 'A'.
const intersectionAB3 : IntersectionAB = {
  a2: 'xxx',
  b1: 'xxx',
  b2: 'xxx',
};
jyztefdp

jyztefdp4#

想想,你可以把赋给这些类型,而不是交叉和合并类型本身。

type I = string & number;
type U = string | number;

const i: I = 5;

失败,我们希望i同时是字符串和数字,但这是不可能的(I在这里是never)。

const u: U = 5;

u可以是字符串或数字,所以可以
回到你的例子:

const obj2: IntersectionType = {
    a: 6,
    b: true,
}

由于obj2与IntersectionType相交(同时具有属性ab),因此可以正常工作。TypeScript在obj2中的属性上循环,并发现IntersectionType的所有必要属性都存在。
还有

const obj: UnionCombinedType = {
    a: 6,
    b: true,
}

typescript 看obj ...... obj是否具有A所需的属性?是的。这对TS来说足够了。
如果您将属性c添加到两个对象,TS将失败,因为它对于两种类型都是未知属性,但这是另一回事。

nhaq1z21

nhaq1z215#

让我们看一下它们每个名称的meanings,而不是使用的signs
意思是不要指望工会|'作为异或,不要将交集'&'作为和的组合。
从意义上看,Union是许多事物的联合,对于Intersection来说,它实际上是两个或更多事物的交集。
让我们举个例子:

interface Human{
 firstName: string;
 lastName: string;
 }

interface Programmer{
 programmingLanguage: string;
 salary: number;
}

//you can get values from both interfaces
const UnionType: Human|Programmer={firstName: "Will",lastName: "Smith",programmingLanguage:"Typescript"};

//you can't get any value from both interfaces because there is no intersection value between them, but you can take all the values, because in this case, the intersection value is all the values from both interfaces.
const IntersectionType: Human & Programmer={firstName: "Will",lastName: "Smith",programmingLanguage:"TypScript",salary:2300};

我强烈推荐阅读这篇文章TypeScript and Set Theory,以获得更多关于并集和交集的概念的理解。

相关问题