Typescript 联合类型-允许使用不同的子类型|

Typescript 联合类型-允许使用不同的子类型|,typescript,Typescript,我输入了一个名为Entry,即: export type Entry = { number: number position: number entryItem: Banana | Orange } 然后我将entryItem类型定义为: 香蕉型 export type Banana = { number: number bananaTitle: string } export type Apple = { number: number appleTitle: s

我输入了一个名为
Entry
,即:

export type Entry = {
  number: number
  position: number
  entryItem: Banana | Orange
}
然后我将entryItem类型定义为:

香蕉型

export type Banana = {
  number: number
  bananaTitle: string
}
export type Apple = {
  number: number
  appleTitle: string
}
苹果类型

export type Banana = {
  number: number
  bananaTitle: string
}
export type Apple = {
  number: number
  appleTitle: string
}
现在,如果我这样做:

entry.entryItem.bananaTitle
我得到一个错误:“属性‘bananaTitle’不存在于‘香蕉|苹果’类型上”

同样,如果我这样做:

entry.entryItem.appleTitle
我得到一个错误:“属性'appleTitle'不存在于'Banana | Apple'类型上”

我的理解是,操作员
|
允许我创建一个类型,当我执行类似于
entry.entryItem.UNIQUE_PROPERTY_OF_Banana_或_Apple
的操作时,如果我指的是
香蕉
或苹果,该类型可以“聪明地”理解


我遗漏了什么?

编译器不是魔术师。属性
entryItem
可能是
Banana
Apple
。由于我们处于编译级别,您必须告诉编译器当前对象是什么。有不同的方法。其中之一是在操作符中使用
,例如:

function test(entry: Entry) {
  if ("appleTitle" in entry.entryItem) {
     entry.entryItem.appleTitle; // it's an apple
  } else {
    entry.entryItem.bananaTitle; // it's a banana
  }
}

有两种观点需要考虑。创建条目的代码和使用条目的代码。这种类型意味着,如果您正在创建一个条目,那么entryItem可以是香蕉或苹果。你有比其他情况更多的选择

但对于使用该条目的代码,它所包含的信息比其他情况下要少。你可能在和一个苹果打交道,或者你可能在和一个香蕉打交道。无法自动判断,因此默认行为是您只能访问保证存在的属性。即,在这两种类型上都可以找到属性

如果您想编写专门与苹果或香蕉交互的代码,那么您首先需要编写代码,找出您要处理的是哪一个

一种方法是使用
in
操作符查看属性是否存在:

const Example = (entry: Entry) => {
  if ('appleTitle' in entry.entryItem) {
    // Inside this block, typescript knows that item must be an Apple, so you can access things found only on apples.
    console.log(entry.entryItem.appleTitle);
  } else {
    console.log(entry.entryItem.bananaTitle);
  }
}
另一个选项是将类型更改为“”。换句话说,在这两种类型上都有一些属性,它们可以唯一地标识我们正在处理的是什么。例如:

export type Banana = {
  type: 'banana',
  number: number
  bananaTitle: string
}

export type Apple = {
  type: 'apple',
  number: number
  appleTitle: string
}

// then use it like:
const Example = (entry: Entry) => {
  if (entry.entryItem.type === 'apple') {
    // Inside this block, typescript knows that item must be an Apple, so you can access things found only on apples.
    console.log(entry.entryItem.appleTitle);
  } else {
    console.log(entry.entryItem.bananaTitle);
  }
}

第三个选项是创建一个

谢谢!如果我通过添加一个
类型
来使用
有区别的联合
方法,那么假设后端也应该更改并包括该
类型
是否公平?