javascript - 联合接口(interface)类型上不存在属性

标签 javascript typescript type-safety union-types

我有一个包含团队成员数组的对象,最小的对象类型实现接口(interface)成员接口(interface)管理器。管理器对象可以包含其他接口(interface)成员对象。每个成员/经理都有自己的key: string

正如你从代码中看到的,我正在尝试实现一个函数setProfession(key, professional),它为某个成员设置profession: string属性/经理基于他们的个人key: string

我的 setProfession 函数中出现此错误:

Property 'members' does not exist on type 'Member | Manager'.

我不明白这个错误,因为我在错误所在行的前面放置了一个安全防护。然而,即使 interface Manager 显然包含 members 属性,它仍然会引发错误: Error printscreen

interface Member {
  key: string;
  name: string;
  profession: string;
}

interface Manager {
  key: string;
  name: string;
  profession: string;
  members: Array<Member>
}

interface Team {
  members: Array<Member | Manager>
}

const TEAM: Team = {
  members: [
    {
      key: 'RodneyMcKay1',
      name: 'Rodney McKay',
      profession: 'Scientist'
    }, {
      key: 'JohnShephard1',
      name: 'John Shephard',
      profession: 'Soldier',
      members: [
        {
          key: 'TeylaEmmagan1',
          name: 'Teyla Emmagan',
          profession: 'Soldier'
        }, {
          key: 'RononDex1',
          name: 'Ronon Dex',
          profession: 'Soldier'
        }
      ]
    }
  ]
};

const isManager = (member: Member | Manager): member is Manager => {
  return member.hasOwnProperty('members');
}

const setProfession = (key: string, profession: string): boolean => {
  for (let i = 0; i < TEAM.members.length; i++) {
    if (isManager(TEAM.members[i])) {    // SAFE GUARD 
      for (let j = 0; j < TEAM.members[i].members.length; j++) {    // ERROR
         if (TEAM.members[i].members[j].key === key) {    // ERROR
           TEAM.members[i].members[j].profession = profession;    // ERROR
           return true;
         }
      }
    } else if (TEAM.members[i].key === key) {
      TEAM.members[i].profession = profession;
      return true;
    }
  }

  return false;
}

最佳答案

Typescript 无法完全跟踪那里的所有钻取。您可以通过将测试值分配给变量来帮助解决这个问题:

  for (let i = 0; i < TEAM.members.length; i++) {
    const person = TEAM.members[i]
    
    if (isManager(person)) {
      for (let j = 0; j < person.members.length; j++) {
         if (person.members[j].key === key) {
           person.members[j].profession = profession;
           return true;
         }
      }
    } else if (person.key === key) {
      person.profession = profession;
      return true;
    }
  }

See playground


如果您使用迭代而不是索引循环,这会变得容易得多。然后,您可以免费获得作为该循环的一部分创建的变量。而且您的代码更容易阅读和理解,这是一个额外的好处。

  for (const person of TEAM.members) {
    if (isManager(person)) {
      for (const member of person.members) {
         if (member.key === key) {
           member.profession = profession;
           return true;
         }
      }
    } else if (person.key === key) {
      person.profession = profession;
      return true;
    }
  }

See playground

关于javascript - 联合接口(interface)类型上不存在属性,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/72905123/

相关文章:

javascript - 如何在 Redux 中使用级联更新对相互依赖的数据进行建模?

javascript - String.match() 函数即使匹配也返回 null

meteor - "TypeError: Cannot read property ' getLocation ' of null"启动angular2-meteor项目时

typescript - 我可以使用相对路径来配置 typescript sdk 吗?

scala - 这是一个类型检查器错误吗?

objective-c - 在 Swift 中检查 [NSObject : AnyObject]! 是否为 NSNull

haskell - 在 Haskell 中使用类型别名的正确方法是什么

javascript - 确定 Mongoose 中空数组和未定义数组之间的区别

javascript - 获取不可见的内部div

angular - ng2-select 中的数据绑定(bind)失败