很多时候都有这样的需求:我想看看这个数据是不是符合这个type
或者interface
但是很遗憾,typescript
本身不提供这样的功能,所以需要迂回地来实现
首先,有一种描述数据格式的工具是json-schema
,社区中有比较成熟的校验数据是否符合格式的工具
而我也找到了一种可以从typescript类型定义生成json-schema
的工具,这样,分成两步即可达到目的
ts结构定义生成json-schema
使用ts-json-schema-generator
可以完成这项工作,而且它支持enum
、import
等常见语法(某些其他npm工具可能不支持)
首先准备好一个类型文件
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 | // data/demo.ts export enum DemoEnum { A = 0, B = 1, } export interface Image { url: string; width?: number; height?: number; } export interface DemoType { id: string; title?: string; count?: number; type: DemoEnum; images?: Image[]; } |
我们在安装该npm包之后,在package.json
的script
中加入一句命令:
1 | ts-json-schema-generator --path data/demo.ts > data/demo.json |
效果:
1 2 3 | "scripts": { "demo-json-schema-builder": "ts-json-schema-generator --path data/demo.ts > data/demo.json" }, |
然后执行可以得到data/demo.json
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 | { "$schema": "http://json-schema.org/draft-07/schema#", "definitions": { "DemoEnum": { "enum": [ 0, 1 ], "type": "number" }, "DemoType": { "additionalProperties": false, "properties": { "count": { "type": "number" }, "id": { "type": "string" }, "images": { "items": { "$ref": "#/definitions/Image" }, "type": "array" }, "title": { "type": "string" }, "type": { "$ref": "#/definitions/DemoEnum" } }, "required": [ "id", "type" ], "type": "object" }, "Image": { "additionalProperties": false, "properties": { "height": { "type": "number" }, "url": { "type": "string" }, "width": { "type": "number" } }, "required": [ "url" ], "type": "object" } } } |
使用json-schema来验证数据
这一步使用jsonschema
这个npm包
1 2 3 4 5 6 7 8 | // run.ts import { Validator } from 'jsonschema'; import * as demoTypes from '../data/demo.json'; const validator = new Validator(); validator.addSchema(demoTypes); const schema = demoTypes.definitions.DemoType; const result = validator.validate(data_to_check, schema, { allowUnknownAttributes: true }); console.log(result, result.errors); |
不错。
还有一个办法,是不是可以用reflect-metadata在运行时做呢
这就要引入额外的代码了,而且看起来ts的type还是没有办法带到runtime,必须重新写一遍