使用打字稿非歧视工会

时间:2019-08-15 02:22:29

标签: typescript type-inference unions

我想知道是否有一种明智的方法来使以下内容正常工作。

interface IPerson {
  firstName: string
  lastName: string
}

interface IPet {
  name: string
}

type IPersonOrPet = IPerson | IPet

function fullname(p: IPersonOrPet) {
  if (p.name) {                                     // **1**
    return p.name                                   // **2**
  } else {
    return p.firstName + ' ' + p.lastName           // **3**
  }
}

我看到有了歧视性工会,情况比较简单,但我看不出为什么非歧视性工会不起作用:

  • 1 我可以想象,打字稿在这里抱怨是因为不知道p.name是否存在。但是,有没有比使用any更好的方法了?
  • 2 但是,这里知道它存在并且是非空的。这样的推断在很多地方都有效,为什么不在这里?
  • 3 这显然是错误的,因为未命名的宠物(例如{name: ''})可以到达它。由于我不知道如何解决前两点,所以我只能在这里猜测。

2 个答案:

答案 0 :(得分:2)

在TypeScript中解决此问题的正确方法是使用类型保护,该函数的返回类型确认或拒绝您关于p属于PersonPet的假设。

查看isPerson()函数的返回类型:

interface Person {
  firstName: string
  lastName: string
}

interface Pet {
  name: string
}

type PersonOrPet = Person | Pet

function fullname(p: PersonOrPet) {
  if (isPerson(p)) {
    return p.firstName + ' ' + p.lastName;
  } else {
    return p.name;
  }
}

function isPerson(p: PersonOrPet): p is Person {
  return 'firstName' in p && 'lastName' in p;
}

答案 1 :(得分:1)

您可以use the in operator as a type guard使用哪种打字稿来适当缩小条件主体中的类型。

function fullname(p: IPersonOrPet) {
  if ('name' in p) {                                // **1**
    return p.name                                   // **2**
  } else {
    return p.firstName + ' ' + p.lastName           // **3**
  }
}