核心问题

能不能让非法状态根本表达不出来?

工程困境

坏模型:

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 必须带 paidAtrefundedAt

Atlas Action

找一组互斥 boolean。把它改写成一个枚举或 union 草稿。

小结

最好的校验,是让错误状态无法被构造出来。