【问题标题】:Conditional type with a Union带有联合的条件类型
【发布时间】:2019-01-23 22:51:05
【问题描述】:

我正在合并两个包含不同类型数据的数组。使用这两种类型的并集,它看起来像这样:

interface Animal {
  animalid: number;
  species: string;
}

interface Person {
  personid: number;
  name: string;
}

const animals: Animal[] = getAnimals();
const people: Person[] = getPeople();

const bothThings: (Animal|Person)[] = [...animals, ...people];

我希望能够调用传入动物或人的 id 的函数,但 id 根据类型位于不同的属性中:分别为 animalidpersonid。我可以根据 id 属性计算出我需要的属性以及它的类型,但我无法使用它,因为我收到 TypeScript 错误:Property 'animalid' does not exist on type 'Animal|Person'. Property 'animalid' does not exist on type 'Person'.

const indexOfThing: number;
let id: number;

...

if (bothThings[indexOfThing].hasOwnProperty('animalid')) {
  id = bothThings[indexOfThing].animalid // TypeScript Error
} else if (bothThings[indexOfThing].hasOwnProperty('personid')) {
  id = bothThings[indexOfThing].personid // TypeScript Error
}

functionThatNeedsId(id);

如何根据条件正确设置类型,或者有更好的方法来实现这一点?

谢谢,

【问题讨论】:

  • Animal[] 或 Person[] 到底长什么样子?
  • @basic 这些只是示例,但我现在为每个示例都包含了一个可能的接口

标签: javascript typescript


【解决方案1】:

令人困惑的是,当您在运行时使用hasOwnProperty 缩小类型时,您实际上并没有在编译时这样做,因此编译器会抱怨。

您可以使用type guards解决此问题

如果您执行以下操作,那么它可能会起作用:

const animals: Animal[] = getAnimals();
const people: Person[] = getPeople();

function isAnimal(animalOrPerson : Animal|Person) : animalOrPerson is Animal {
    return (object as Animal).animalid !== undefined;
} 

function isPerson(animalOrPerson  : Animal|Person) : animalOrPerson is Person {
    return (object as Person).personid!== undefined;
} 


const bothThings: (Animal|Person)[] = [...animals, ...people];

if (isAnimal(bothThings[indexOfThing])) {
  id = bothThings[indexOfThing].animalid 
} else if (isPerson(bothThings[indexOfThing].hasOwnProperty('personid'))) {
  id = bothThings[indexOfThing].personid 
}

这样做将使编译器能够正确确定条件内对象的实际类型。

【讨论】:

    【解决方案2】:

    试试这个:

    if (bothThings[indexOfThing].hasOwnProperty('animalid')) {
      id = (bothThings[indexOfThing] as Animal).animalid
    } else if (bothThings[indexOfThing].hasOwnProperty('personid')) {
      id = (bothThings[indexOfThing] as Person).personid
    }
    

    【讨论】:

      猜你喜欢
      • 2021-06-04
      • 2019-08-27
      • 2019-04-06
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-04-14
      • 2022-10-17
      • 1970-01-01
      相关资源
      最近更新 更多