mcpField
P
principle-type-system-discipline

principle-type-system-discipline

github.com/poteto开发161112 次安装22 周前更新
代码仓库

关于 principle-type-system-discipline

一项适用于多种类型语言的开发技能,指导开发者利用类型系统消除无效状态并尽早发现错误。内容涵盖数据建模、边界校验和穷尽匹配。

主要功能

  1. 01用显式变体建模无效状态
  2. 02为语义原始类型添加品牌
  3. 03在边界解析非类型化数据
  4. 04避免不安全的类型转换
  5. 05要求穷尽匹配变体
  6. 06从权威模式派生类型

适用场景

  1. 01安全表达互斥状态
  2. 02区分含义不同的标识符
  3. 03校验 RPC、JSON 或配置输入
  4. 04确保新增变体触发编译期检查

安装

复制下面的命令,在终端中运行。

$npx skills add https://github.com/poteto/plugins --skill principle-type-system-discipline

安装后在 Claude Code 中输入/principle-type-system-discipline确认已加载。

详细介绍

类型系统规范

类型检查器是一个证明助手。利用它在编译时排除不可能的状态、不匹配的基本类型和未处理的变体。任何被当作运行时数据放行的内容,都可能导致编译器原本能够阻止的运行时故障。

适用于任何带类型的语言。typescript-best-practices 等技能会将其落实到特定语法中。

这些模式:

  • 让非法状态无法表示。 将变体建模为和类型:TypeScript 中的判别联合类型,Rust/Swift/Kotlin 中带负载的枚举,Scala 中的密封类,Haskell/OCaml 中的代数数据类型。不要把状态建模为一组可选字段,因为互相矛盾的组合也能通过编译。一个值得指出的微妙反模式是:{ completed: boolean; completedAt?: Date } 允许 completed: true; completedAt: undefined 这种毫无意义的情况。应从 completedAt !== null 这样的单一来源推导布尔值,或显式建模不同变体,例如 { kind: 'open' } | { kind: 'done'; at: Date }。如果出现 bug 后,你不得不问“等等,这种组合真的可能发生吗?”,说明类型约束太宽松。
  • 为具有语义的基本类型添加标记。 UserId 和 OrderId 底层都是字符串,但不应可以互换。可使用 Rust 中的新类型、Swift 中的不透明类型、Kotlin 中的值类、Haskell 中的幻影类型,以及 TypeScript 中的品牌交叉类型。在创建时验证一次,后续就可以信任该类型。
  • 外部数据在解析之前都没有类型。 RPC 负载、JSON、IPC 消息、CLI 参数、配置文件、环境变量、数据库行。应在每个边界设置解析函数,将非结构化输入转换为带类型的模型。关于验证应放在哪里,请参阅 boundary-discipline 原则技能。
  • 不要欺骗类型系统。 类型转换、不安全强制转换,以及绕过编译器的断言函数,都是随时可能发生的运行时崩溃。如果编译器无法证明某个事实,就应予以证明(验证、缩窄类型、细化模型),或承认类型转换存在风险。今天埋下的类型转换,就是你下周要写的事故复盘。
  • 穷尽匹配是编译器的职责。 匹配和类型时,如果新增变体却未处理,编译器必须阻止编译。使用语言提供的惯用方式:TypeScript 中绑定为 never 类型,Rust 中不加注解的 match,Haskell 中的 -Wincomplete-patterns,Kotlin 中密封类匹配的穷尽性检查。
  • 从权威模式定义派生类型。 当协议缓冲区、OpenAPI 规范、GraphQL 模式、数据库迁移或设计系统令牌文件定义了某种结构时,应从中派生,而不是手动另建一套并行类型。手动重复定义迟早会出现偏差。请参阅 encode-lessons-in-structure 原则技能。
  • 优先选择编译时检查,而不是运行时检查。 每个运行时断言、空值检查和 instanceof,都意味着类型系统没有发挥应有的作用。应将检查前移到类型层面。

检查问题:

  • “我能否写一条注释,说明这些字段组合在什么情况下有效?”如果能,说明类型约束太宽松。应将其拆分为和类型。
  • “我的两个函数参数是否具有相同的基本类型,但含义不同?”为它们添加标记。
  • “这个 any、这个 as、这个 assertNotNull 是从哪里来的?”追溯到边界,并在那里进行验证。
  • “如果下个月新增一个变体,编译器会告诉下一个 Agent 应该在哪里添加分支吗?”如果不会,说明匹配并不穷尽。
  • “这个类型是否重复定义了另一个文件所拥有的结构?”应从权威定义派生。

评论

支持 Markdown