小知识,大挑战!本文正在参与“程序员必备小知识”创作活动。
背景
最近在开发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对代码规范、效能提升上是否存在帮助。希望看到这篇文章的你,能动手实现下,收获超乎你想象。