You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何用TypeBox创建支持运行时动态范围验证的自定义Schema

问题描述

我们有如下TypeScript接口:

interface RangedNumber {
   value: number;
   minValue: number;
   maxValue: number;
}

可通过以下TypeBox Schema生成对应类型:

const Schema = Type.Object({
  value: Type.Number(),
  minValue: Type.Number(),
  maxValue: Type.Number(),
});

type RangeNumber = Static<typeof Schema>;

但该Schema仅能验证各属性的类型。已知可向Type.Number()传入minimum和maximum参数:

value: Type.Number({ minimum: x, maximum: y }),

但minValue和maxValue的具体值仅在运行时可知。现需创建符合要求的自定义TypeBox Schema,使得如下示例可通过验证:

{
   value: 5,
   minValue: 0,
   maxValue: 10,
}

而如下示例无法通过验证:

{
   value: 200,
   minValue: 0,
   maxValue: 10,
}

请问最优实现方案是什么?

最优实现方案

使用Type.Refine添加跨字段验证

TypeBox的Type.Refine方法可以在基础类型之上添加自定义断言逻辑,完美适配这种需要根据对象内部其他字段值做验证的场景。

实现代码如下:

import { Type, Static } from '@sinclair/typebox';

// 定义基础对象结构
const BaseRangedNumberSchema = Type.Object({
  value: Type.Number(),
  minValue: Type.Number(),
  maxValue: Type.Number(),
});

// 扩展添加跨字段验证
const RangedNumberSchema = Type.Refine(BaseRangedNumberSchema, (data) => {
  return data.value >= data.minValue && data.value <= data.maxValue;
}, {
  message: 'value必须介于minValue和maxValue之间'
});

// 生成TypeScript类型
type RangedNumber = Static<typeof RangedNumberSchema>;

验证效果

配合Ajv(TypeBox常用的验证引擎)使用:

import Ajv from 'ajv';

const ajv = new Ajv();
const validate = ajv.compile(RangedNumberSchema);

// 合法数据验证通过
console.log(validate({ value: 5, minValue: 0, maxValue: 10 })); // true

// 非法数据验证失败
console.log(validate({ value: 200, minValue: 0, maxValue: 10 })); // false
console.log(validate.errors); // 输出自定义错误信息

方案优势

  • 类型安全:生成的RangedNumber类型完全继承原接口的类型定义,保留TypeScript静态类型检查能力。
  • 运行时可靠:跨字段验证逻辑在运行时生效,精准拦截不符合规则的数据。
  • 实现简洁:基于基础类型扩展,无需复杂的自定义关键字或额外工具链。

内容的提问来源于stack exchange,提问作者ThdK

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.17 04:07:40