Typescript中的對象多可能類型推導的解決辦法

我們在渲染複雜對象,比如樹組件的樹對象,有嵌套對象/數組結構的時候,js的弱類型讓我們一把梭,幾乎沒遇到什麼問題(只是寫的時候編譯沒問題把。233。。),結合TS後,對樹狀數據的遞歸訪問會是一個問題:

比如數據源的數據聲明爲:

export interface VoiceSkillResponse {
  data: {
    isExistUpdate: number;
    isNewProduct: number;
    streamList: {
      streamId: string;
      streamName: string;
      intentList: {
        id: number;
        intent: string;
        isSelect: number;
      }[];
    }[];
  };
}

export interface VoiceSkill {
  streamId: string;
  streamName: string;
  intentList: Array<Intent>;
}

export interface Intent {
  id: number;
  intent: string;
  isSelect: number;
}

我們想根據這樣的數據渲染一個樹組件

  function renderNode(dataList: Array<VoiceSkill | Intent>) {
    dataList.map((v, k) => {
      if (v.intentList) {
        return (
          <Tree name={v.streamName} key={v.streamName}>
            {renderNode(v.intentList)}
          </Tree>
        );
      } 
      return <Tree name={v.intent} key={v.id} />;
    });
  }

| 的寫法並不能讓TS自動推導出v的類型和是否有訪問屬性,所以直接在編譯層報錯。

查閱TS文檔:文檔鏈接

我們可知至少兩種解決方法:

as暴力

缺點,寫很多as吧

  function renderNode(voiceSkillList: Array<VoiceSkill | Intent>) {
    voiceSkillList.map((v, k) => {
      if ((v as VoiceSkillList).intentList) {
        return (
          <Tree name={(v as VoiceSkillList).streamName} key={(v as VoiceSkillList).streamName}>
            {renderNode((v as VoiceSkillList).intentList)}
          </Tree>
        );
      }
      return <Tree name={(v as IntentList).intent} key={(v as IntentList).id} />;
    });
  }
寫一個函數類型保護

個人認爲目前最適合的方式?也是官方文檔給的一種方式

  function isVoiceSkill(item: VoiceSkill | Intent): item is VoiceSkill {
    return (item as VoiceSkill).intentList !== undefined;
  }
  function renderNode(dataList: Array<VoiceSkill | Intent>) {
    dataList.map((v, k) => {
      if (isVoiceSkill(v)) {
        return (
          <Tree name={v.streamName} key={v.streamName}>
            {renderNode(v.intentList)}
          </Tree>
        );
      } else {
        return <Tree name={v.intent} key={v.id} />;
      }
    });
  }
函數重載

大佬說的一種,但是這樣的話相當於參數在函數裏還是any吧, 失去了類型檢查…?重載主要是在調用的時候做類型檢查用的,存疑。。。

  function renderNode(dataList: VoiceSkill[]): Array<React.ReactElement<any>>;
  function renderNode(dataList: Intent[]): Array<React.ReactElement<any>>;
  function renderNode(dataList: any[]): Array<React.ReactElement<any>> {
    return dataList.map((v, k) => {
      if (v.intentList) {
        return (
          <Tree name={v.streamName} key={v.streamName}>
            {renderNode(v.intentList)}
          </Tree>
        );
      }
      return <Tree name={v.intent} key={v.id} />;
    });
  }
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章