如何获取类型为多个联合接口类型的 属性 的值?

How can I get the value of a property of type multiple union interface types?

我有以下代码:

  const arrayFromForm: IFirst[] | ISecond[] | IThird[]; // = ... it's initialized
  const arrayDB: IFirst[] | ISecond[] | IThird[]; // = ... it's initialized
  const entitiesFromDb = arrayDB.filter(
    (entity: IFirst | ISecond | IThird) =>
      !(arrayFromForm.map(({ id }) => id))
      .includes(entity.id)
  );

它给了我 1 个错误:"The map expression is not callable"

如果我错了请纠正我,但我认为这是因为它不知道联合中的所有接口中都有一个名为 id 的 属性。


我以前使用过类型保护,但我认为您只能在联合中的 2 种类型之间创建类型保护,因为您必须 return 布尔值?

我想用 typescript(用户定义的类型保护、typeof、instanceof 等)解决这个问题,但我不确定这是否可行,不是吗? instanceof 不能为接口创建类型保护,对吗?
好的解决方案是什么?


编辑:我刚刚用一个接口解决了这个问题,该接口具有联合中的接口共有的属性,并且我只是用新接口更改了类型联合。这不是很好的解决方案,因为我想在类型联合中的不同接口中使用特定的 methods/properties。

所以我不会删除这个问题,因为它仍然有助于了解是否存在诸如用户定义的类型保护之类的东西,用于其中包含 2 种以上类型的类型联合。

试试这个:-

const elementsIds = arrayFromForm.filter(arrItem => arrItem.id).map((item)=>item.id); 
  const entitiesFromDb = arrayDB.filter(
    (entity: IFirst | ISecond | IThird) =>
      !elementsIds.includes(entity.id)
  )

这似乎是 Typescript 中的一个已知问题。参见 Here

但现在您可以这样做:

const arrayFromForm: IFirst[] | ISecond[] | IThird[]; // = ... it's initialized
const entitiesFromDb = arrayDB.filter(
  (entity: IFirst | ISecond | IThird) =>
    !(arrayFromForm as {id: number}[]).map(item => item.id).includes(entity.id) // Pay attention to the brackets
);

我们将 arrayFromForm 转换为一种合适的类型,而不是类型的联合。这与您提出的解决方案很接近,但我认为以这种方式维护起来更容易。