TypeScript 属性描述符:模式验证的类型安全错误处理
在 JavaScript 项目中,开发者常常为验证复杂嵌套对象而烦恼。传统方法使用字符串路径提取错误,容易在重构时引发运行时 bug。解决方案?属性描述符:一个结构化的属性描述符树,提供类型安全的选择器,并支持完整的 IDE 自动补全。
核心思路是,每个模式构建一个节点树,每个描述符都知道自己的属性路径、关联模式、父级以及访问方法。这样,你可以用 Lambda 表达式编译选择器,而不是脆弱的字符串。
import { object, string, number, InferType } from '@cleverbrush/schema';
const OrderSchema = object({
id: string(),
customer: object({
name: string().minLength(2),
email: string().email(),
address: object({
city: string().required('City is required'),
zip: number()
})
}),
total: number().min(0)
});
const result = OrderSchema.validate({
id: '123',
customer: {
name: 'A',
email: 'not-an-email',
address: {
zip: -1
}
},
total: -5
});
const nameErrors = result.getErrorsFor(t => t.customer.name);
const cityErrors = result.getErrorsFor(t => t.customer.address.city);
重命名字段,TypeScript 会在编译时捕获错误。IDE 提供完整的自动补全。
不可变流式 API 和构建器
所有模式方法调用都返回新实例,避免突变。这让组合和复用变得轻而易举。
库提供了 14 种构建器类型:
string()— minLength、maxLength、matches、email、url、uuidnumber()— min、max、positive、negative、finite、multipleOfboolean()— 基础验证date()— minDate、maxDateobject()— 命名属性array()— 类型化元素、非空union()— 判别联合tuple()— 固定长度record()— 动态键func()— 函数类型any()— 带 hasTypenul()— nulllazy()— 递归模式extern()— Standard Schema v1 包装器
基础 SchemaBuilder 的常用方法:
.optional()— 接受 undefined.required('msg')— 必填字段.nullable()— 接受 null.default(value)— 默认值.catch(value)— 错误回退.readonly()— Readonly<T>.brand<'T'>()— 品牌类型.describe('text')— 保留 JSDoc.addValidator(fn)— 自定义逻辑.addPreprocessor(fn)— 预处理.introspect()— 元数据
运行时模式自省
.introspect() 方法返回完整的模式描述:类型、约束、标志、描述、扩展。运行时全部可用,适用于工具和集成。
const Name = string().minLength(2).maxLength(100).describe('User name').optional();
const info = Name.introspect();
// info.type === 'string'
// info.minLength === 2
// info.description === 'User name'
自省功能针对每个构建器完全展开。完美适用于 JSON Schema 转换、表单生成或自定义渲染器。
类型化扩展系统
扩展是可组合、可自省的核心插件。例如 HEX 颜色和端口:
const hexColorExt = defineExtension({
string: {
hexColor(this: StringSchemaBuilder) {
return this.addValidator((v) => {
const valid = /^#[0-9a-f]{6}$/i.test(v as string);
return {
valid,
errors: valid ? [] : [{ message: 'Must be a valid HEX color' }]
};
});
}
}
});
const s = withExtensions(hexColorExt, portExt);
const colorSchema = s.string().hexColor();
扩展出现在 .introspect().extensions 中。内置包括 email、url、uuid、positive、非空。
Standard Schema v1 兼容性
模式实现了 Standard Schema v1,与 tRPC、TanStack Form、React Hook Form、Hono 无缝集成。extern() 将 Zod/Valibot 包装成构建器。
const UserSchema = object({
name: string().minLength(2),
address: extern(zodAddress)
});
属性描述符即使在混合模式中,也提供类型安全的错误访问。
核心要点
- 类型安全选择器:通过属性描述符消除字符串路径和运行时 bug。
- 不可变流式 API:简化无副作用组合。
- 运行时自省:为任意工具提取元数据。
- 扩展:类型化、可组合的核心插件。
- Standard Schema v1:确保生态兼容性。
— Editorial Team
暂无评论。