zoukankan      html  css  js  c++  java
  • 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} />;
        });
      }
    
  • 相关阅读:
    机器学习-分类算法-决策树,随机森林10
    机器学习-分类算法-模型选择与调优09
    机器学习-分类算法-精确率和召回率08
    机器学习-分类算法-朴素贝叶斯算法07
    机器学习-分类算法-K-近邻算法06
    java读取自定义配置文件并引用
    kafka发布消息报错LEADER_NOT_AVAILABLE
    Kettle位置参数(Argument)、命名参数(Parameter)、变量(Variable)
    kettle里的两个参数和一个变量
    如何在命令行下运行kettle的作业(job)和转换(transform)
  • 原文地址:https://www.cnblogs.com/zhangmingzhao/p/11752408.html
Copyright © 2011-2022 走看看