

使用TypeScript校验运行时数据
source link: https://segmentfault.com/a/1190000040652111
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

对于前端程序猿,常见的开发流程是:
- 前后端约定接口
- 后端给出接口文档
- 根据接口编写 TypeScript 类型定义
- 开发完成进行联调
虽然一切顺利,但是上线后还是翻车了,js 报错:cannot read the property 'xx' of null
,很显然前端没有处理空值,接锅吧 TT。但回头一看接口文档,跟后端同学约定的返回对象,但实际返了 null
,这锅不能一个人背。那么怎样才能尽早发现这种问题呢?一种解决方案是:
- 将 TypeScript 类型定义转为 JSON Schema
- 利用 JSON Schema 校验数据正确性
针对以上方案做了一个 demo
JSON Schema
JSON Schema 是一个 JSON 对象,用来描述和校验 JSON 对象的格式。比如下面这个 JSON Schema:
{ "type": "object", "properties": { "name": { "type": "string" }, "age": { "type": "number" }, "hobby": { "type": "array", "items": { "type": "string" } } }, "required": [ "age", "hobby", "name" ], "$schema": "http://json-schema.org/draft-07/schema#", }
它描述了这样一个 JSON 对象:
- 类型 -
type
是obeject
有四个属性 -
properties
name
:类型为string
age
:类型为number
hobby
:类型为Array<string>
- 属性是否必须 -
required
:name
,age
,hobby
都为必须
下面这个 JSON 对象就是满足这个 JSON Schema 的:
{ "name": "Tom", "age": 1, "hobby": ["coding"] }
可以看出 JSON Schema 还是很好理解的,但其描述语法还是有一定学习成本,这里强烈推荐通过 jsonschema 库的 example 去学习相关语法,另外也可以看 Understanding JSON Schema。
有了 JSON Schema,怎么使用它校验 JSON 对象的合法性呢?这里就用到了刚刚提到的jsonschema 库。简单使用示例如下:
var Validator = require('jsonschema').Validator; var v = new Validator(); var instance = 4; var schema = {"type": "number"}; console.log(v.validate(instance, schema));
现在可以根据 JSON Schema 去校验后端返回数据的格式是否正确了,但是为每个接口手动编写 JSON Schema 是不现实的,我们自然会想到能不能将 TypeScript 的接口类型定义转为 JSON Schema?
TypeScript Interface -> JSON Schema
好在已经有 typescript-json-schema 这个库帮我们解决了这个问题,下面给出简单的使用示例:
import path from "path"; import * as TJS from "typescript-json-schema"; const settings: TJS.PartialArgs = { required: true }; // optionally pass ts compiler options const compilerOptions: TJS.CompilerOptions = { strictNullChecks: true }; // 解析接口定义文件:index.ts const program = TJS.getProgramFromFiles( [path.join(__dirname, './apis/index.ts')], compilerOptions, ); // 将"IApi1"这个interface转为schema,传入"*"将转换全部interface let schema = TJS.generateSchema(program, "IApi1", settings) || {};
一顿操作后就可以将下面这个 interface
转为文章开头给出的示例 JSON Schema:
interface IApi1 { name: string; age: number; hobby: string[]; }
然后再用 node 将刚刚得到的 schema 存成 json 文件:
fs.writeFileSync(path.join(__dirname, "./json-schema", "schema.json"), schema);
接着就可以使用相应的 JSON Schema 对后端数据进行校验了:
import { Validator } from 'jsonschema' const apiSchema = require('./json-schema/schema.json') const v = new Validator(); Api1().then(res => { const validateRes1 = v.validate(res, apiSchema) console.log(validateRes1); });
完整的示例可以看:demo
工程中的实践
1、如何组织散落的接口类型定义?
我个人比较喜欢的方式是:在 apis.ts
文件中统一去写所有的接口定义和类型定义,这样在转换 JSON Schema 时去处理这一个文件即可。
2、怎样自动将类型定义转为 JSON Schema?
使用 husky
,在 pre-commit
阶段去执行转换工作,进一步可以使用 lint-staged
判断当前提交是否涉及到接口定义文件的改动,有改动再执行转换。
关于脚本的编写:
首先创建脚本
touch scripts/transfer.js
transfer.js
中去编写 TS 转为 JSON Schema 的逻辑package.json
中添加scripts
:"scripts": { "transfer": "node scripts/transfer.js" }
或者在
pre-commit
中去执行该脚本。
3、何时校验数据?
这里我想到两个场景:
- 生产上:对于一些关键接口,在接口返回数据后调用校验逻辑,如果校验有错,需要做两件事:第一是将错误数据转为正确的备用数据,以防页面挂掉;第二是上报错误;
- 测试时:写各种测试用例去测后端接口,校验返回数据的正确性,这样就不用人眼去校验数据是否正确了。
Recommend
-
82
-
96
编者按:本文转载自 ThinkJS 知乎专栏。 Web 服务的整个流程中,获取数据是最重要的一环,如何方便快捷的获取用户提交的数据减少开发者的开发成本是一个 Web 服务框架应该考虑的事情。本文将会为大家介绍在 ThinkJS 中请求数据解...
-
39
前端开发过程中你们觉得处理什么业务功能最烦人? 做前端已经有很长一段时间了,不知道大家是否和我有同样的感受,在一些 Web 应用中表单处理起来比其他功能模块都麻烦,很多体力活,往往在数据的校验会很费时间。 为了能够把这部分代码更有条理,我们把数据校验部...
-
45
项目实践仓库 https://github.com/durban89/typescript_demo.git tag: 1.3.8 为了保证后面的学习演示需要安装下ts-node,这样后面的每个操作都能直接运行看到输出的结果。 npm install -D ts-node...
-
74
本文首发于 github 博客 如文章对你有帮助,你的 star 是对我最大的支持 背景 大家出来写 Bug 代码的,难免会出 Bug。 文章背景就发生在一个 Bug 身上, 有一天,测试慌张中带着点兴奋冲过来: 测试:"xxx系统前端线上出 Bug 了,点
-
45
-
11
前言 最近优化 gin+vue的前后端分离项目 代码时候,发现代码中对请求数据的校验比较繁琐,于是想办法简化它。最终我发现了
-
37
经过了为期 2 年的开发,Deno 终于在 2020 年的 5 月份完成了 1.0 版本 。其 官方网站 宣称,Deno 为 JavaScript 和 TypeScript 提供了一个安全的运行时环境。听...
-
27
主从数据不一致对DBA来说是一个比较头疼的事情,刚接触MySQL时,遇到这种问题我一般采用重新还原备库的方式恢复数据,这对我来说是个很痛苦的过程。今天就来介绍两款pt工具,通过这两款工具可以针对数据不一致的情况进行快速检测...
-
8
使用Dgg实现MySQL数据库同构跨库数据校验 在使用Dgg实现MYSQL跨库数据同步后,可以使用Dgg的数据校验功能来验证数据是否一致。 请首先参考《使用Dgg 全量同步/初始化Initial Load MySQL数据》 https://www.askmac.cn/archives/...
About Joyk
Aggregate valuable and interesting links.
Joyk means Joy of geeK