Drizzle ORM 中 nullable 字段在插入时的类型问题解析
问题背景
在使用 Drizzle ORM 时,开发者经常会遇到一个类型系统问题:当表结构中包含可为空(nullable)的字段时,在创建插入操作时会遇到 TypeScript 的类型错误。这个问题在 drizzle-orm 0.38.2 版本中尤为明显,表现为 TypeScript 报错"Object literal may only specify known properties",即对象字面量只能包含已知属性。
问题表现
在定义表结构时,如果某些字段被设置为可为空(如使用 .default(null) 或不加 .notNull()),在后续的插入操作中,TypeScript 会错误地认为这些字段不应该出现在插入值中。例如:
const users = pgTable("users", {
id: integer("id").primaryKey().notNull().unique(),
firstName: varchar("first_name", { length: 255 }).default(null),
lastName: varchar("last_name", { length: 255 }).default(null),
username: varchar("username", { length: 255 }).notNull()
});
当尝试插入数据时:
await db.insert(users).values({
id: 1,
username: "test",
firstName: "John", // 这里会报类型错误
lastName: "Doe" // 这里会报类型错误
});
TypeScript 会提示 firstName 和 lastName 不是有效的属性。
技术原因
这个问题的根本原因在于 Drizzle ORM 的类型推断系统($inferInsert)在处理可为空字段时,没有正确地将这些字段标记为可选属性。在 TypeScript 的类型系统中,一个字段如果是可选的,应该使用 ? 标记,如 { prop?: string }。
在 Drizzle ORM 0.38.2 版本中,类型系统错误地将所有字段(无论是否为 nullable)都视为必须属性,导致在实际插入操作时,TypeScript 认为开发者试图添加不存在的属性。
解决方案
这个问题在 drizzle-orm 0.38.3 和 drizzle-zod 0.6.1 版本中已得到修复。升级到这些版本后,类型系统会正确识别可为空字段,并将其标记为可选属性。
对于使用 createInsertSchema 的情况,解决方案类似:
export const createAuthSchema = createInsertSchema(authTable, {
data: z.record(z.unknown()) // 显式指定复杂类型的验证规则
}).omit({
createdAt: true,
updatedAt: true
});
最佳实践
-
保持依赖更新:始终使用最新版本的 Drizzle ORM 和相关库,以避免已知的类型问题。
-
显式类型定义:对于复杂字段(如 JSON 类型),建议显式定义其 Zod 验证规则。
-
类型检查:在开发过程中,定期检查生成的类型是否符合预期,特别是在表结构变更后。
-
测试覆盖:为数据库操作编写类型测试,确保类型系统按预期工作。
总结
Drizzle ORM 的类型系统在大多数情况下都能提供良好的类型安全,但在处理可为空字段时曾经存在缺陷。通过理解问题的本质和解决方案,开发者可以更高效地使用这个 ORM 工具,同时享受 TypeScript 带来的类型安全优势。记住,保持库的更新是避免这类问题的最简单方法。
Kimi-K2.5Kimi K2.5 是一款开源的原生多模态智能体模型,它在 Kimi-K2-Base 的基础上,通过对约 15 万亿混合视觉和文本 tokens 进行持续预训练构建而成。该模型将视觉与语言理解、高级智能体能力、即时模式与思考模式,以及对话式与智能体范式无缝融合。Python00
GLM-4.7-FlashGLM-4.7-Flash 是一款 30B-A3B MoE 模型。作为 30B 级别中的佼佼者,GLM-4.7-Flash 为追求性能与效率平衡的轻量化部署提供了全新选择。Jinja00
VLOOKVLOOK™ 是优雅好用的 Typora/Markdown 主题包和增强插件。 VLOOK™ is an elegant and practical THEME PACKAGE × ENHANCEMENT PLUGIN for Typora/Markdown.Less00
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
KuiklyUI基于KMP技术的高性能、全平台开发框架,具备统一代码库、极致易用性和动态灵活性。 Provide a high-performance, full-platform development framework with unified codebase, ultimate ease of use, and dynamic flexibility. 注意:本仓库为Github仓库镜像,PR或Issue请移步至Github发起,感谢支持!Kotlin07
compass-metrics-modelMetrics model project for the OSS CompassPython00