基于JS实现将JSON数据转换为TypeScript类型声明的工具

 更新时间:2023年04月03日 10:58:42   作者:forrest酱  
在TypeScript 项目中,我们经常需要使用声明一系列的ts类型。然而,手动写的效率实在太低,本文就实现一个工具将 JSON 数据转换为 TypeScript 类型定义,需要的可以参考一下

在TypeScript 项目中,我们经常需要使用声明一系列的ts类型。然而,手动写的效率实在太低,编写一个自动生成ts类型的工具可以解放生产力。 实现一个工具将 JSON 数据转换为 TypeScript 类型定义,从而让 TypeScript 项目更高效的开发。

一、实现的功能

  • 将 JSON 数据转换为 TypeScript 类型定义。
  • 支持嵌套的复杂类型,如数组和对象。
  • 支持自定义类型名称和命名空间。
  • 支持将转换后的 TypeScript 类型定义保存为文件。

二、工具使用方法

已经发布到npm:my-json-to-ts - npm (npmjs.com)

运行效果如下动图:

安装工具:

npm install -g my-json-to-ts

运行工具:

my-json-to-ts input.json output.ts

其中 input.json 是要转换的 JSON 文件路径,output.ts 是转换后的 TypeScript 文件路径。

--name 类型名称    # 指定转换后的类型名称,默认为 JsonType
--namespace 命名空间 # 指定转换后的命名空间,默认为无
--no-file          # 不将转换后的 TypeScript 类型定义保存为文件

三、实现思路

  • 读取输入的 JSON 文件,解析成 JSON 对象。
  • 遍历 JSON 对象,根据不同的类型生成对应的 TypeScript 类型定义字符串。
  • 如果指定了类型名称和命名空间,则在生成的 TypeScript 类型定义字符串前面添加对应的声明。
  • 如果指定了保存文件,则将生成的 TypeScript 类型定义字符串写入文件。

四、使用示例

以下是将JSON 数据和转换后的 TypeScript 类型定义示例:

简单的JSON 数据

{
  "name": "John",
  "age": 30,
  "address": {
    "city": "New York",
    "state": "NY"
  },
  "hobbies": [
    "reading",
    "traveling"
  ]
}

输出对应简单的类型定义

interface JsonType {
  name: string;
  age: number;
  address: {
    city: string;
    state: string;
  };
  hobbies: string[];
}

复杂的JSON 数据

{
  "name": "John",
  "age": 30,
  "address": {
    "city": "New York",
    "state": "NY",
    "postalCode": 10001
  },
  "friends": [
    {
      "name": "Jane",
      "age": 28,
      "address": {
        "city": "Los Angeles",
        "state": "CA"
      }
    },
    {
      "name": "Bob",
      "age": 35,
      "address": {
        "city": "Chicago",
        "state": "IL"
      }
    }
  ],
  "hobbies": [
    "reading",
    "traveling",
    {
      "name": "swimming",
      "location": "pool"
    }
  ]
}

输出对应复杂类型定义

interface JsonType {
  name: string;
  age: number;
  address: {
    city: string;
    state: string;
    postalCode: number;
  };
  friends: {
    name: string;
    age: number;
    address: {
      city: string;
      state: string;
    };
  }[];
  hobbies: (string | {
    name: string;
    location: string;
  })[];
}

五、具体实现代码

首先引入两个 Node.js 模块:fs-extracommanderfs-extra 是一个简化了 Node.js 文件系统模块的封装,而 commander 是一个命令行工具的库,可以方便地解析命令行参数。

接下来定义一个函数 jsonToTs,用于将 JSON 数据转换为 TypeScript 类型定义字符串。该函数采用递归的方式遍历 JSON 数据,生成对应的 TypeScript 类型定义。如果 JSON 数据是数组,则递归处理其中的每个元素;如果是对象,则递归处理其中的每个属性。最终,该函数返回一个 TypeScript 类型定义字符串。

然后定义了两个异步函数,readJsonwriteTs,分别用于读取 JSON 文件和将 TypeScript 类型定义字符串写入文件。

最后定义一个名为 jsonToTsFile 的函数,该函数接收命令行参数并将其传递给 jsonToTs 函数,然后将生成的 TypeScript 类型定义字符串保存到文件中。如果命令行参数中指定了不保存文件,则该函数将直接将 TypeScript 类型定义字符串输出到控制台。

  const fs = require('fs-extra');
  const commander = require('commander');

  /**
   * 将 JSON 数据转换为 TypeScript 类型定义
   * @param {Object} object - 要转换的 JSON 对象
   * @param {string} [name=JsonType] - 转换后的类型名称
   * @param {string} [namespace] - 转换后的命名空间
   * @returns {string} - 转换后的 TypeScript 类型定义字符串
   */
  function jsonToTs(object, name = 'JsonType', namespace) {
      const getType = value => {
          let typeRes = ``;
          if (Array.isArray(value)) {
              value.forEach(item => {

                  let subType = getType(item);
                  if (typeRes.split('|').indexOf(subType) < 0) {
                      typeRes += subType
                      typeRes += "|"
                  }
              })
              typeRes = typeRes.substring(0, typeRes.length - 1)
              return `(${typeRes})[]`;
          }
          if (typeof value === 'object' && value !== null) {
              const props = Object.entries(value)
                  .map(([key, val]) => `${key}: ${getType(val)}`)
                  .join('; ');
              return `{ ${props} }`;
          }
          return typeof value;
      };

      const type = getType(object);

      const declaration = `interface ${name} ${type}`;

      return namespace ? `namespace ${namespace} { \r\n ${declaration} \r\n}` : declaration;
  }

  /**
   * 读取文件并解析成 JSON 对象
   * @param {string} path - 文件路径
   * @returns {Promise<Object>} - JSON 对象
   */
  async function readJson(path) {
      const content = await fs.readFile(path, 'utf8');
      return JSON.parse(content);
  }

  /**
   * 将 TypeScript 类型定义字符串写入文件
   * @param {string} content - TypeScript 类型定义字符串
   * @param {string} path - 文件路径
   * @returns {Promise<void>}
   */
  async function writeTs(content, path) {
      await fs.writeFile(path, content, 'utf8');
  }

  /**
   * 将 JSON 数据转换为 TypeScript 类型定义
   * @param {string} inputPath - 输入 JSON 文件路径
   * @param {string} outputPath - 输出 TypeScript 文件路径
   * @param {string} [options.name=JsonType] - 转换后的类型名称
   * @param {string} [options.namespace] - 转换后的命名空间
   * @param {boolean} [options.noFile] - 不将 TypeScript 类型定义保存为文件
   * @returns {Promise<void>}
   */

  async function jsonToTsFile(inputPath, outputPath, options) {
      const { name, namespace, noFile } = options
      try {
          const object = await readJson(inputPath);
          const type = jsonToTs(object, name, namespace);
          if (noFile) {
              console.log(type);
          } else {
              await writeTs(type, outputPath);
              console.log(`Type definition saved to ${outputPath}`);
          }
      } catch (err) {
          console.error(err.message);
      }
  }

  const program = new commander.Command();

  program
      .arguments('<input> <output>')
      .option('--no-file', 'do not save to file')
      .option('-s, --namespace <namespace>', 'type namespace')
      .option('-n, --name <name>', 'type name', 'JsonType')
      .action(jsonToTsFile);

  program.parse(process.argv);

六、写在最后

这个工具可以极大地提高在 TypeScript 项目中编写类型声明的效率。通过输入一个 JSON 数据,它可以自动生成对应的 TypeScript 类型定义,支持复杂类型,如数组和对象,并支持自定义类型名称和命名空间。此外,还可以选择将转换后的 TypeScript 类型定义保存为文件。

到此这篇关于基于JS实现将JSON数据转换为TypeScript类型声明的工具的文章就介绍到这了,更多相关JS实现JSON转TypeScript类型声明内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • JS+Canvas实现的俄罗斯方块游戏完整实例

    JS+Canvas实现的俄罗斯方块游戏完整实例

    这篇文章主要介绍了JS+Canvas实现的俄罗斯方块游戏,结合完整实例形式分析了Canvas技术实现俄罗斯方块游戏的步骤、技术难点与相关实现技巧,需要的朋友可以参考下
    2016-12-12
  • 通过大白话理解微信小程序获取授权

    通过大白话理解微信小程序获取授权

    最近由于公司需要研究了一下微信小程序的开发,特此记录一下小程序获取授权的流程,便于自己理解,下面这篇文章主要给大家介绍了关于如何通过大白话理解微信小程序获取授权的相关资料,需要的朋友可以参考下
    2022-12-12
  • JavaScript 中的12种循环遍历方法【总结】

    JavaScript 中的12种循环遍历方法【总结】

    本文给大家总结了12种JavaScript 中的1循环遍历方法,每种方法通过实例代码给大家介绍的非常详细,具有一定的参考借鉴价值,需要的朋友可以参考下
    2018-05-05
  • 可自定义速度的js图片无缝滚动示例分享

    可自定义速度的js图片无缝滚动示例分享

    这篇文章主要介绍了非常平滑的JS图片滚动特效代码,无缝循环,速度可自定义,大家参考使用吧
    2014-01-01
  • js微信分享API

    js微信分享API

    这篇文章主要为大家详细介绍了js微信分享实现代码,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2016-07-07
  • JavaScript交换两个变量方法实例

    JavaScript交换两个变量方法实例

    这篇文章主要介绍了JavaScript交换两个变量方法实例,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下
    2019-11-11
  • 通过构造函数实例化对象的方法

    通过构造函数实例化对象的方法

    下面小编就为大家带来一篇通过构造函数实例化对象的方法。小编觉得挺不错的,现在就分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2017-06-06
  • 微信小程序云开发之使用云数据库

    微信小程序云开发之使用云数据库

    这篇文章主要为大家详细介绍了微信小程序云开发之使用云数据库,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2019-05-05
  • 用javascript关闭本窗口技巧小结

    用javascript关闭本窗口技巧小结

    window.close()是用来关闭窗口的,而且ie和firefox都是支持的,下面通过示例为大家介绍下用javascript关闭本窗口
    2014-09-09
  • 用javascript模仿ie的自动完成类似自动完成功的表单

    用javascript模仿ie的自动完成类似自动完成功的表单

    最近在写一个javascript框架,看见网上有不少自动完成功能的表单,于是用javascript写了一个,需要的朋友可以参考下
    2012-12-12

最新评论