Valibot 中如何预定义 ObjectSchema 的键类型
2025-05-30 03:40:33作者:滑思眉Philip
在 Valibot 这个强大的 TypeScript 表单验证库中,开发者有时会遇到需要预定义 ObjectSchema 键类型的场景。本文将深入探讨这一技术问题的解决方案。
问题背景
当开发者尝试构建自定义的 useForm 钩子时,常常需要确保验证模式中的键与表单字段完全匹配。例如,当表单字段定义为 { name: "", email: "" } 时,验证模式应该强制包含且仅包含 name 和 email 这两个键。
技术挑战
Valibot 的 ObjectSchema 类型通常用于定义对象验证模式,但在 TypeScript 中直接使用它作为泛型时可能会遇到类型推断问题。开发者需要找到一种既能保持类型安全又能提供良好开发体验的解决方案。
解决方案
经过探索,我们发现了两种有效的实现方式:
方案一:分离验证条目与对象创建
type SchemaEntries<TValues> = {
[TKey in keyof TValues]: GenericSchema<TValues[TKey], unknown>;
};
interface FormConfig<TValues, TEntries extends SchemaEntries<TValues>> {
fields: TValues;
validation?: TEntries;
}
function useForm<TValues, TEntries extends SchemaEntries<TValues>>(
config: FormConfig<TValues, TEntries>
) {
const schema = config.validation && object(config.validation);
}
这种方案将验证条目与对象创建分离,允许 TypeScript 在配置阶段就进行类型检查,然后在函数内部创建实际的验证对象。
方案二:直接使用 ObjectSchema 类型
type SchemaEntries<TValues> = {
[TKey in keyof TValues]: GenericSchema<TValues[TKey], unknown>;
};
interface FormConfig<TValues, TEntries extends SchemaEntries<TValues>> {
fields: TValues;
validation?: ObjectSchema<
TEntries,
ErrorMessage<ObjectIssue> | undefined
>;
}
function useForm<TValues, TEntries extends SchemaEntries<TValues>>(
config: FormConfig<TValues, TEntries>
) {
// 实现代码
}
这种方案直接使用 ObjectSchema 类型,保持了 Valibot 原生 API 的使用方式,同时通过泛型约束确保了类型安全。
实际应用示例
const form = useForm({
fields: {
username: "",
age: 0,
},
validation: {
username: string(),
age: pipe(number(), minValue(18)),
},
});
在这个例子中,TypeScript 会确保:
- 验证对象必须包含
username和age两个键 - 每个键对应的验证器类型必须与字段类型匹配
- 如果缺少必要键或添加了额外键,都会引发类型错误
技术原理
这两种方案都利用了 TypeScript 的映射类型和泛型约束:
SchemaEntries<TValues>创建了一个类型,其键与TValues相同,但值类型为对应的验证器- 泛型约束
TEntries extends SchemaEntries<TValues>确保传入的验证配置与字段定义匹配 - 方案一在运行时创建验证对象,方案二直接使用预构建的验证对象
最佳实践建议
- 对于简单表单,方案二更为直接
- 对于需要动态构建验证规则的复杂场景,方案一更具灵活性
- 始终为表单字段提供初始值,这有助于 TypeScript 正确推断类型
- 考虑添加自定义错误消息等增强功能时,可以扩展
SchemaEntries类型
通过这种方式,开发者可以在 Valibot 中实现类型安全的表单验证,获得完整的类型检查和编辑器自动补全功能,大大提升开发效率和代码可靠性。
登录后查看全文
热门项目推荐
相关项目推荐
Kimi-K2.5Kimi K2.5 是一款开源的原生多模态智能体模型,它在 Kimi-K2-Base 的基础上,通过对约 15 万亿混合视觉和文本 tokens 进行持续预训练构建而成。该模型将视觉与语言理解、高级智能体能力、即时模式与思考模式,以及对话式与智能体范式无缝融合。Python00- QQwen3-Coder-Next2026年2月4日,正式发布的Qwen3-Coder-Next,一款专为编码智能体和本地开发场景设计的开源语言模型。Python00
xw-cli实现国产算力大模型零门槛部署,一键跑通 Qwen、GLM-4.7、Minimax-2.1、DeepSeek-OCR 等模型Go06
PaddleOCR-VL-1.5PaddleOCR-VL-1.5 是 PaddleOCR-VL 的新一代进阶模型,在 OmniDocBench v1.5 上实现了 94.5% 的全新 state-of-the-art 准确率。 为了严格评估模型在真实物理畸变下的鲁棒性——包括扫描伪影、倾斜、扭曲、屏幕拍摄和光照变化——我们提出了 Real5-OmniDocBench 基准测试集。实验结果表明,该增强模型在新构建的基准测试集上达到了 SOTA 性能。此外,我们通过整合印章识别和文本检测识别(text spotting)任务扩展了模型的能力,同时保持 0.9B 的超紧凑 VLM 规模,具备高效率特性。Python00
Baichuan-M3-235BBaichuan-M3 是百川智能推出的新一代医疗增强型大型语言模型,是继 Baichuan-M2 之后的又一重要里程碑。Python00
VLOOKVLOOK™ 是优雅好用的 Typora/Markdown 主题包和增强插件。 VLOOK™ is an elegant and practical THEME PACKAGE × ENHANCEMENT PLUGIN for Typora/Markdown.Less00
项目优选
收起
deepin linux kernel
C
27
11
OpenHarmony documentation | OpenHarmony开发者文档
Dockerfile
539
3.76 K
Ascend Extension for PyTorch
Python
348
414
本项目是CANN提供的数学类基础计算算子库,实现网络在NPU上加速计算。
C++
889
609
openEuler内核是openEuler操作系统的核心,既是系统性能与稳定性的基石,也是连接处理器、设备与服务的桥梁。
C
338
185
openJiuwen agent-studio提供零码、低码可视化开发和工作流编排,模型、知识库、插件等各资源管理能力
TSX
986
252
openGauss kernel ~ openGauss is an open source relational database management system
C++
169
233
暂无简介
Dart
778
193
🎉 (RuoYi)官方仓库 基于SpringBoot,Spring Security,JWT,Vue3 & Vite、Element Plus 的前后端分离权限管理系统
Vue
1.34 K
758
华为昇腾面向大规模分布式训练的多模态大模型套件,支撑多模态生成、多模态理解。
Python
114
140