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

从代码中可以看出,我正在try 实现一个函数setProfession(key, profession),该函数根据某个成员/经理的个人key: string为其设置profession: string属性.

my setProfession函数中存在以下错误:

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

我不理解这个错误,因为我在错误所在的线路前放了一个安全防护装置.尽管interface Manager显然包含members属性,但它仍然会抛出一个错误:

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相关问答推荐

react 页面更改类别时如何返回第0页

Angular 拦截器错误处理删除方法问题

Fastify错误:CORS策略已阻止从起源api-dev.example.com上的MLhttp请求

在卡信息之间切换

Angular:ng-contract未显示

使用useup时,React-Redux无法找到Redux上下文值

传递一个大对象以在Express布局中呈现

仅针对RTK查询中的未经授权的错误取消maxRetries

如何粗体匹配的字母时输入搜索框使用javascript?

CheckBox作为Vue3中的一个组件

为什么按钮会随浮动属性一起移动?

阿波罗返回的数据错误,但在网络判断器中是正确的

如何从网站www.example.com获取表与Cheerio谷歌应用程序脚本

用JS从平面文件构建树形 struct 的JSON

如何在JAVASCRIPT中临时删除eventListener?

无法读取未定义的属性(正在读取合并)-react RTK

OnClick更改Json数组JSX中的图像源

图表4-堆叠线和条形图之间的填充区域

Clip-Path在网页浏览器(Mozilla、Edge、Chrome)上不能正常工作,但在预览版Visual Code Studio HTML、CSS、JS上却能很好地工作

我不知道如何纠正这一点.