TypeScript自定义类型守卫冗余问题:如何避免重复校验定义?
如何让TypeScript自动生成类型守卫以校验HTTP请求体?
手动编写自定义类型守卫确实会存在重复定义类型逻辑、容易漏检或校验错误的问题,你可以通过以下两种方式实现自动化的类型校验:
方案一:基于JSON Schema的自动校验
先将TypeScript类型转换为JSON Schema,再用Schema校验库做运行时校验,无需手动编写类型守卫:
- 安装依赖:
npm install ts-json-schema-generator ajv --save-dev
- 生成JSON Schema:
创建脚本generate-schema.ts,将你的IdealRequestBody类型转为Schema:
import { generateSchema } from 'ts-json-schema-generator'; import fs from 'fs'; const config = { path: './src/types.ts', // 你的类型定义文件路径 tsconfig: './tsconfig.json', type: 'IdealRequestBody', // 目标类型名 }; const schema = generateSchema(config); fs.writeFileSync('./src/request-body-schema.json', JSON.stringify(schema, null, 2));
- 运行时校验:
在代码中用ajv加载Schema并校验请求体:
import Ajv from 'ajv'; import schema from './request-body-schema.json'; const ajv = new Ajv(); const validate = ajv.compile(schema); function checkRequestBody(requestBody: any): requestBody is IdealRequestBody { return validate(requestBody); }
方案二:用Zod实现“一次定义,双重作用”
Zod是一个TypeScript优先的Schema声明库,它允许你定义一次Schema,同时生成TypeScript类型并做运行时校验,完全避免重复定义:
- 安装依赖:
npm install zod
- 定义Schema并导出类型:
import { z } from 'zod'; // 先定义CategoryShares的Schema const CategorySharesSchema = z.object({ // 这里根据你的CategoryShares类型定义对应校验规则,比如: foo: z.string(), bar: z.number(), }); // 定义IdealRequestBody的Schema const IdealRequestBodySchema = z.object({ seed: z.string(), categoryShares: CategorySharesSchema, }); // 从Schema自动推导TypeScript类型 export type IdealRequestBody = z.infer<typeof IdealRequestBodySchema>;
- 校验请求体:
function checkRequestBody(requestBody: any): requestBody is IdealRequestBody { const result = IdealRequestBodySchema.safeParse(requestBody); return result.success; }
如果需要更详细的错误信息,可以直接使用parse方法(校验失败时抛出错误),或者通过result.error获取具体错误。
这两种方案都能避免手动编写冗余的类型守卫逻辑,其中Zod的写法更简洁直观,适合大多数TypeScript项目;JSON Schema方案则更适合需要跨语言、跨系统共享校验规则的场景。
内容的提问来源于stack exchange,提问作者VictorHjelmberg
相关产品推荐
相关产品推荐

