Tealina: 让全栈项目拥有端到端类型和API文档

1,498 阅读2分钟

什么是端到端类型?

相较于传统的开发流程 (后端写接口,前端将每个接口封装成请求函数), 端到端类型是让前端直接引用后端接口定义,从而减少重复编码,降低维护成本。

Tealina 通过一系列创新,让全栈开发拥有端到端类型和API文档,其核心是将后端定义的API转换成一个特定的类型, 大概是这样👇: (如果不喜欢看解释,这里有高清视频演示)

// types/api-v1.d.ts
type ApiTypesRecord = { //一个两层结构的对象
  post: { //第一层key是 http method
    "category/create": { //第二层key是 URL
      body: BodyType;
      response: ResonseType;
      //...parmas,header,query
    };//第二层值是具体的数据类型
  };
};

后端怎么做才能得到一个这样的数据结构?
约定文件结构,存放API的目录第一层是 http-method,第二层以下是每个具体API文件,用index.ts将当前层级目录下文件导出,代码如下:

//api-v1/index.ts
export default {
    'post': import('./post/index.js'),//.js是新版Node的要求
    //...
}
```

```ts
//api-v1/post/index.ts
export default {
    'user/create': import('./user/create.js'),
    //...
}

有了这样的文件结构, 后续只需要导入 `api-v1/index.ts` 文件,就可以拿到 api-v1 目录下所有API,顺便实现了批量导出,方便路由注册。 配合TS的 typeof 关键字,将对象转成类型。 

// types/api-v1.d.ts
import apis from './src/api-v1/index.js'
type RawApiType = typeof apis

具体的body,response这些信息如何获取?

类型别名, 定义一个 HandlerType<Tinput, Toutput, Theader>,然后约定所有API文件默认导出这个类型,就可以通过infer关键字拿到。

//types/handler.ts

//简化版
type HandlerType<T extends RawPayload, Treponse, Theaders> = (req,res) => any

type ExtractApiType<T> = T extends HandlerType<
  infer Payload,//用infer提取对应位置的类型
  infer Response,
  infer Headers
>
  ? Payload & { response: Response; headers: Headers } //组合成对象
  : never

interface RawPayload {
  body?: unknown
  params?: unknown
  query?: unknown
}

现在,你应该能看懂这张图:

有了API类型,前端可以基于它封装请求函数, 无需手动定义类型。 API文档也可以通过解析这个类型来生成, 有了约定的文件结构,自动化(生成api文件,更新index.ts)也就随之而来, 每个API通常会用到的类型基本是基于model定义的,那提供一个基于model生成类型的功能,很合理吧, 而这些,就是Tealina的功能。

为了更方便使用,Tealina提供脚手架工具 create-tealina: 用于创建开箱即用的全栈项目:

# pnpm
pnpm create tealina

# yarn
yarn create tealina

# npm
npm create tealina@latest

关联项目:

  1. tealina: 命令行工具,用于生成类型,文档,用它创建和删除API文件会自动更新index.ts

  2. @tealina/doc-ui: 作用类似swagger-ui, 拥有更加现代的界面和更强的功能

  3. @tealian/doc-types: API文档类型,doc-ui就是根据它做的,你也可以借助它将API文档生成其他代码

高清视频演示
中文文档: cn.tealina.dev
GitHubgithub.com/tealina/tea…