SDK

    2. 前端极速提效SDK开发(二)

    Published
    December 16, 2022
    Reading Time
    2 min read
    Author
    Felix

    前情提要

    前面我们分析一个宏观的开发思路,接下来我们就直接步入正题,进入开发,而我们首先需要想明白很多边界和细节问题因为实际通常这些问题会莫名其妙占用你很多时间

    边界:我们在开发的过程中会遇到特别多的边界问题,但我们的开发定位是一个提效工具,处理边界的问题是为了去收窄正确的思路,而不是强制去处理用户的东西(你把握不住的),说得不好听一点他要是个xx,他给你这种{'a ': 1, ' a': 2, '1#@#@#xx':3}数据,这是属于开发接口的出数据的人的责任了。我们要做的边界指责只在于,你给我正常的数据,我输出正常的interface

    细节:第一个是数据的不可变性这是重中之重。还有就是不能因为一个过度优化去放弃代码可读性(因为每次我看到那种东西就特别焦灼特别想优化即使会让可读性很差)。第三个还是注意一下时间复杂度的问题。

    输入到中间态

    输入

    对于输入来说我们只处理对象,因为实际上interface并不能很好的直接镶嵌在数组上,你总是会需要多写个[]或者Array,大不了你可以给你的数组外面套一层对象就很好,就像这样。

    let json: Arr = {
      arr: [
        { a: 1, b: 3 },
        { d: 5, h: 6 }
      ]
    };
    // 为自动生成
    interface Arr {
        a?: number;
        b?: number;
        d?: number;
        h?: number;
    }
    interface OriginKey {
        arr: Arr[];
    }
    
    

    因此我们就需要一些限制,限制json = [],可能后续也会考虑要不要直接生成type arr= number[]让你们直接用到数组上,但当前先限制掉,原始类型也不需要处理,我们实际就只处理json对象。在遇到对象以外的数据就直接抛出异常

    const defaultOptions = {
      fKey: 'originKey'
    };
    export default function JsonToTS<JsonTypes>(
      json: JsonTypes,
      options?: finallyOptions
    ): string[] {
      const finallyOptions = {
        ...defaultOptions,
        ...options
      };
    
      const JsonType = getJsonType(json);
      
      if (JsonType === TypeGroup.Object) {
        throw new Error('Only Object are supported');
      }
      // 返回数组结构的types
      const typesValue = getTypesValue(json, finallyOptions);
      typesValue['key'] = finallyOptions.fKey;
      const data = out(typesValue);
      return data;
    }
    
    

    输入-中间态

    可以看到上述代码经过getTypesValue就形成了我们的中间态。上一节我们提到了中间态的选择,我们可以先看看输入和中间态长什么样子。

    let json = {
      a: {
        a: 1,
        b: 2
      },
      c: {
        d: 1,
        g: 2
      }
    };
    
    

    我希望我的输入最终能呈现出这样的中间态

    image.png

    下面是一个处理的思路

    image.png

    我们先进入到我们的中转站,去进行一个类型的分类,当遇到原始值,诸如number Date boolean string等就直接返回,遇到对象或者数组就生成一个types描述数组将key、ype、alue都描述出来,以供后面的生成。顺带一提,Object.entries这个方法需要垫片shim

    function dealObj(obj) {
      const seprateArr = Object.entries(obj).reduce((pre, [key, value]) => {
        const { types, type } = getTypesValue(value);
        let param = {
          type,
          types,
          key,
          value
        };
        pre.push(param);
        return pre;
      }, []);
      return seprateArr;
    }
    
    // 检测器,类型的处理器
    export function getTypesValue(value: any, option?: finallyOptions) {
      const valueBtype = getJsonType(value);
      let typeValue;
      switch (valueBtype) {
        case TypeGroup.Array:
          typeValue = dealObj(value);
          return {
            type: 'Array',
            types: typeValue
          };
        case TypeGroup.Object:
          typeValue = dealObj(value);
          return {
            type: 'Object',
            types: typeValue
          };
        case TypeGroup.Primitive:
          typeValue = getPrimtiveTypeStr(value);
          return {
            type: typeValue
          };
      }
    }
    
    

    但这里我们会发现一个问题,就是生成的描述性数组没有一个key给到最外层,生成interface的时候就会undefined,毕竟我们总是拿到的值又并不知道你声明的变量叫什么,所以这里是给它了一个初始的默认值,你也可以自定义传入的fKey

    image.png

    随便说点

    唔,到这中间态的生成就可以暂时告于段落,其实这是一个很大的集成插件,其他的东西都定制型太强了像服务,平台,组件库对接之类的东西。可能只有interface大伙可以单独拿出来给大伙玩,做了挺多优化的大伙可以试试,看看。github地址,大伙可以点点星什么的。