核心问题
能不能让非法状态根本表达不出来?
工程困境
坏模型:
type Course = {
isDraft: boolean
isPublished: boolean
isArchived: boolean
}
它允许:
isDraft = true
isPublished = true
isArchived = true
思想模型
用类型缩小可能世界。
type CoursePublicationStatus = "draft" | "published" | "archived"
系统现在只能处于一个合法状态。
好模型
更进一步,用 discriminated union:
type Payment =
| { status: "pending" }
| { status: "succeeded"; paidAt: Date }
| { status: "refunded"; paidAt: Date; refundedAt: Date }
refunded 必须带 paidAt 和 refundedAt。
Atlas Action
找一组互斥 boolean。把它改写成一个枚举或 union 草稿。
小结
最好的校验,是让错误状态无法被构造出来。