利用Ts Compiler Api批量修改类型声明小案例

1,277 阅读2分钟

小知识,大挑战!本文正在参与“程序员必备小知识”创作活动。

背景

最近在开发TypeScript 项目,在跟后端交流定义接口协议,发现他们命名规范都是非驼峰,而是以"_"的形式,一项用惯驼峰的我自然很不习惯,因此心生如何自动转换,然后花了点时间实现了下,下面看看实现思路。

实现方案

首先,我司后端接口服务都是通过swagger文档给出,那根据swagger api批量生成接口typescript声明文件,我司采用的是我正在研发的提效工具VsCode插件(未发布到插件市场)。当然目前插件市场也存在类型插件,可自行查找。

下面假设转换后的接口声明是这样的:

interface Statudent {
  stu_id: string,
  stu_name: string,
  stu_age: string,
}

而我们想要的是如下的定义:

interface Statudent {
  stuId: string,
  stuName: string,
  stuAge: string,
}

如何处理呢?
学过编译原理、或者看过babel/loader的实现,可以大体得出思路流程如下:

输入-> 编译 -> 转化 -> 输出

看到这就懂下面怎么做了,找 TypeScript Compiler Api !
官方文档关于这块api的介绍使用不完整也不详细,并且全是英文,使用案例也不多,看着不是太友好,因此翻看了会,决定上npm找个简易封装的库。

ts-morph : TypeScript编译器包装器,npm 周下载量 637,804

下面上简易代码:

import * as ts from 'typescript'
import { default as tspro, Project } from 'ts-morph'

function transformToCamel(fileName:string, template: string){
  const project = new Project()
  // 创建
  const sourceFile = project.createSourceFile(fileName, template)
  // 转换
  sourceFile.transform((traversal) => {
    const node = traversal.visitChildren()
    // 判断是 interface 声明节点
    if (ts.isInterfaceDeclaration(traversal.currentNode)){
      // 节点属性: members: interface内部属性成员
      const { decorators, modifiers, name, typeParameters, heritageClauses, members } = traversal.currentNode
      // 数据转换:获取的节点属性都是只读,不能直接修改
      const element = members.map((item: { name: { escapedText: string } }) => ({
          ...item,
          // 名字转驼峰
          name: ts.factory.createIdentifier(toCamelUtil(item.name.escapedText, false, '_')),
        })) as unknown as ts.TypeElement[]
      // 创建成员
      const memberArr = ts.factory.createNodeArray(element)
      // 返回新创建的interface声明
      return ts.factory.createInterfaceDeclaration(
          decorators,
          modifiers,
          name,
          typeParameters,
          heritageClauses,
          memberArr
        )
    }
    return node
  })
}

总结

借助这个小案例也算初步了解了ts编译器的使用,当你打断点取调试,你可以知道ast树是怎样的,compiler api都能干什么,基于这些api对代码规范、效能提升上是否存在帮助。希望看到这篇文章的你,能动手实现下,收获超乎你想象。