TypeScript结构类型检查-联合和相交类型

时间:2019-12-22 10:41:16

标签: typescript

我是打字稿新手。我一直在玩联合体和交集类型的形状,遇到了意料之外的事情……

如果我如下创建两个形状:

type Person = {
    name: string,
    occupation?: string
}

type Animal = {
    name: string
    gestationPeriodDays: number
}

然后我创建这两个形状的结合以及相交,就像这样...

type AnimalUnionPerson = Animal | Person

let humanzeeAllFields: AnimalUnionPerson = {
    name: "Humanzee",
    gestationPeriodDays: 60,
    occupation: "Banana Farmer"
}

type AnimalIntersectPerson = Animal & Person 

let animalIntersectPerson = {
    name: "Shape Intersect",
    gestationPeriodDays: 24,
    occupation: "Data Scientist"
}

然后我创建了一个简单的函数,将交集类型作为参数...

function printOutIntersection(toPrint: AnimalIntersectPerson) {
    console.log(toPrint.name)
    console.log(toPrint.occupation) // With union of shapes, no need for User Defined Type Guard
    console.log(toPrint.gestationPeriodDays)
}

现在,我可以将animalIntersectPerson传递给函数,但是即使形状本身具有相同的字段,也不能将humanzeeAllFields传递给函数。我希望能够给出TypeScript执行的结构类型检查。有人可以解释为什么会这样吗?

2 个答案:

答案 0 :(得分:2)

事实上,AnimalUnionPersonAnimalIntersectPerson没有提供相同的结构:

AnimalUnionPerson
- name //required
- occupation //optional
- gestationPeriodDays //Because of the union typing this is optional
AnimalIntersectPerson
- name //required
- occupation //optional
- gestationPeriodDays //in this case it's required

如您所见,gestationPeriodDays的状态会根据使用并集键入或交集而改变。

答案 1 :(得分:2)

路口类型

当您拥有类型为Animal & Person的值时,这意味着确保该值是AnimalPerson

联盟类型

给出类型为Animal | Person的值时,它可以是AnimalPerson。可能两者都有。与交集相比,不能保证该值同时为AnimalPerson

为表示一个值是Animal XOR Person,可以使用discriminated union type(求和类型)。


继续您的示例:

printOutIntersection需要交集类型Animal & PersonhumanzeeAllFields是联合类型Animal | Person,因此不能确保同时为AnimalPerson

由于Person不是assignableAnimal(仅Animal具有gestationPeriodDays属性),因此调用printOutIntersection无效类型为humanzeeAllFields的{​​{1}}。

Playground