likes
comments
collection
share

做了一个将 JSON 转换为 TypeScript 接口的小工具 欢迎体验

作者站长头像
站长
· 阅读数 13

做了一个将 JSON 转换为 TypeScript 接口的小工具

当我们使用 TypeScript 开发时,我们经常需要定义接口来描述数据的结构。这些接口可以帮助我们在编码过程中避免错误,并提供更好的代码提示和类型检查。

然而,在编写接口时,我们可能会面临一些重复的工作,尤其是当我们需要将一个已有的 JSON 对象转换为 TypeScript 接口时。手动编写这些接口会非常耗时且容易出错。因此,自动化这个过程可以帮助我们提高效率并减少错误。

在本文中,我将介绍一个使用 TypeScript 实现的将 JSON 转换为 TypeScript 接口声明的工具。这个工具可以帮助我们快速地生成 TypeScript 接口声明,从而减少手动编写接口的工作量。

工具的一些截图: 做了一个将 JSON 转换为 TypeScript 接口的小工具 欢迎体验 做了一个将 JSON 转换为 TypeScript 接口的小工具 欢迎体验

实现过程

灵感是来自一篇文章和 json2ts 包,在我点赞中可以找到,其实这个功能整体实现并不是很难的,下面给大家分析要注意的点

用到了什么技术栈:

  1. 语言:typescript
  2. 框架:vue3
  3. 编辑器:monaco-editor
  4. UI:Tiny-Vue 支持 vue2 和 vue3 大家可以尝试使用一下
  5. 函数库:underscore

编辑器操作 useMonaco

  • getCode 获取编辑器代码
  • setCode 设置编辑器代码
import * as monaco from 'monaco-editor';
import { onMounted, onUnmounted } from 'vue';

export default function useMonaco(
  selector: string,
  options?: monaco.editor.IStandaloneEditorConstructionOptions
) {
  const state = {
    editor: null as monaco.editor.IStandaloneCodeEditor | null,
    getCode: () => state.editor?.getValue() || '',
    setTheme: (theme: string) => state.editor?.updateOptions({ theme }),
    setCode: (code: string) => state.editor?.setValue(code),
  };

  onMounted(() => {
    state.editor = monaco.editor.create(
      document.querySelector(selector) as any,
      {
        value: '',
        language: 'json',
        tabSize: 2,
        theme: 'vs-dark',
        ...options,
      }
    );
  });

  onUnmounted(() => (state.editor = null));

  return state;
}

核心转换 jsontots

拆分需求 从最简单的功能到一步步完成其他场景

接下来我们就做一个实现最简单的转换只考虑一种 例如:

{
  "name": "sakana"
}

代码实现:

class Json2Ts {
  
  convert(content: string, interfaceName: string = 'RootTypes'): string {
    let jsonContent = JSON.parse(content);

    let result = this.convertJsonToTsInterfaces(
      jsonContent,
      interfaceName
    );
    return result;
  }
    
  convertJsonToTsInterfaces(jsonContent: any, interfaceName: string){
    let interfaceKeys: string[] = [];
    let objectResult: string[] = [];
	
	for (const key in jsonContent) {
      let value = jsonContent[key];
	  
      jsonContent[key] = this.getType(value); 
      if (this.getType(value) === 'any') {
        interfaceKeys.push(key);
      }
      
    }
    let result = this.formatCharsToTypeScript(
        jsonContent,
        interfaceName,
        interfaceKeys
     );
    objectResult.push(result);
     
    return objectResult.join('');
  }
    
  formatCharsToTypeScript(jsonContent: any, interfaceName: string, optionalKeys: string[]){
     // 将对象转换为字符串 stringify 第二个参数是过滤器,第三个参数是缩进
     let result = JSON.stringify(jsonContent, null, '\t')
      .replace(new RegExp('"', 'g'), '')
      .replace(new RegExp(',', 'g'), '');
      
     let allKeys = _.allKeys(jsonContent)
     for (let index = 0, length = allKeys.length; index < length; index++) {
       let key = allKeys[index]
       
       // 如果在 optionalKeys 中 表示他是一个 any 类型加上可选
       if(_.contains(optionalKeys, key)) {
           result = result.replace(new RegExp(key + ':', 'g'), key + '?:')
       } else {
           result = result.replace(new RegExp(key + ':', 'g'), key + ':')
       }
     }
	 
     return 'export interface ' + interfaceName + ' ' + result;
  }  
  
  getType(value: any): string {
      if(_.isString(value)) {
        return 'string'
	  } else {
        return 'any'
      }
  }
}

以上就是最简单的场景实现 效果如下:

做了一个将 JSON 转换为 TypeScript 接口的小工具 欢迎体验 分析:

  1. convert 他会拿到一份 content 这个其实 JSON 内容 ,然后执行 convertJsonToTsInterfaces
  2. convertJsonToTsInterfaces 中我们会对 所有的 key 进行一个保存在 interfaceKeys 中,通过 for...in 迭代 ,当中我们会去判断是什么类型,通过 getType 方法并且把原本的内容改为类型,当遍历都完成的时候,用 formatCharsToTypeScript 转成 TypeScript 接口
  3. formatCharsToTypeScript 一开始对 jsonContent 去掉当中的"" , 情况,allKeys 拿到所有的 key ,通过循环 判断是不是 any,是的话加上 ?,然后返回

以上就是思路的过程,后面在简单场景上判断其他类型 只需要在 getType 中添加其他,复杂场景只需要递归一下和武装一下判断就好了

仓库我是开源了,代码不多,欢迎大家留言讨论

仓库:jsontots仓库

体验地址:jsontots

总结

在这篇文章中,我介绍了一个使用 TypeScript 实现的将 JSON 转换为 TypeScript 的工具。我们讨论了工具的实现过程,并展示了一些代码和截图,以帮助你更好地理解它的工作原理。

通过使用这个工具,你可以快速地生成 TypeScript 接口声明,从而减少手动编写接口的工作量,并提高代码的可读性和可维护性。