ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

pstack原则09类型系统纪律:如何让非法状态不可表示

pstack原则09类型系统纪律:如何让非法状态不可表示 pstack原则09类型系统纪律如何让非法状态不可表示【免费下载链接】pstack-claudeClaude Code, Codex, Copilot, Pi, OpenCode, Gemini, and Prime Agent versions of Potetos pstack. Rigorous agent workflows with Cursor primitives translated for other harnesses.项目地址: https://gitcode.com/GitHub_Trending/ps/pstack-claudepstack 类型系统纪律是 pstack 原则系列的第 09 条把类型检查器当作证明助手在编译期就消灭非法状态。读完本文你会掌握判别联合、品牌类型、边界解析等 8 个实操模式学会让非法状态不可表示——从源头减少运行时错误而不是出错后再打补丁。为什么需要类型系统纪律类型检查器不只是报错工具它是一位证明助手proof assistant。核心思想一句话类型系统让你忽略掉的每一种情况都会变成编译器本可以阻止的运行时崩溃。比起到处添加防御性检查更好的做法是把错误和特例直接定义到不存在。这条原则适用于任何静态类型语言TypeScript、Rust、Kotlin、Swift……在 pstack 仓库中写作技能文件 principle-type-system-discipline/SKILL.md。判别联合让矛盾状态根本写不出来新手最容易掉进可选字段袋陷阱// 坏味道completed 为 true 却没有时间编译器却不报错 type Task { completed: boolean; completedAt?: Date };这个定义允许已完成但没有完成时间这种无意义的状态。用判别联合discriminated union重写即可// 好每个合法状态都是独立分支非法组合无法构造 type Task { kind: open } | { kind: done; at: Date };每个变体用kind字面量区分已完成但没有时间从此无法被写出。这就是让非法状态不可表示的精髓。类型是构造出来的不是限制出来的别拿运行时检查去雕刻一个宽松类型而是从合法值出发把类型搭起来非空列表 首元素 其余元素而不是列表 到处检查长度有效时间区间 开始时间 时长而不是两个必须手动保序的时间戳原文有个很妙的判据当某个 bug 让你问出等等这种组合真的可能发生吗时说明类型太松了。品牌类型UserId 和 OrderId 不能互换UserId和OrderId底层都是字符串但绝不该互换。用品牌类型branded typesTypeScript 中通常是 { readonly __brand: UserId }这样的交叉类型让编译器拦住参数传错。记住八个字创建时验证一次下游信任类型。边界验证外部数据解析前都是无类型RPC 响应、JSON、命令行参数、环境变量、数据库行……外部数据在解析之前都是无类型的。正确姿势是在每个边界放置解析函数把无结构输入转成类型化模型跨过边界后就信任内部类型不要在调用链深处重复验证。TypeScript 里这意味外部输入应标为unknown而不是any——前者逼你收窄后者只是闭眼。不要对类型系统撒谎as断言、!非空断言、绕过编译器的断言函数都是潜伏的运行时崩溃。如果编译器无法证明某个事实就亲自证明它验证、收窄、细化模型证明不了就承认这个断言是风险点。穷举检查交给编译器对联合类型做匹配时让编译器保证新增变体但没人处理 → 编译失败。TypeScript 的惯用法是在switch的default分支写const _exhaustive: never x;。这样下个月有人加变体时编译器会明确告诉下一个人或下一个 AI Agent该在哪里补 case。从权威 Schema 派生类型如果 protobuf、OpenAPI 或数据库迁移文件已经定义了某种形状从它派生类型而不是手写一个平行接口。重复的形状必然随 schema 演进而漂移。克制只在出现部分性时才强化类型类型系统的职责是跟踪每个调用点必须处理哪些情况而不是把数据描述得越精确越好空列表求和是 0 → 普通T[]就够空列表取首元素无解 → 输入必须是非空版本优先全函数total functions。当某处出现运行时断言、空值检查或这里绝不应该发生的 throw就标记出类型太弱的地方——把检查上提到类型里然后停手。代码评审时的 6 问自检清单 原文附带 6 个自检问题可直接用于 review你能否写一条注释解释这种字段组合何时合法能 → 类型太松拆成联合。两个函数参数同为原始类型、含义却不同→ 加品牌。那个any、as是从哪来的→ 追到边界去验证。新增变体时编译器会告诉下一个人去哪补 case 吗→ 不会就补穷举检查。这个类型是不是复制了别的文件拥有的形状→ 改为派生。我强化类型是为了让操作变全还是单纯想更精确→ 后者就保持简单类型。在 pstack 中如何自动应用这些原则 pstack 是把 Poteto 的 pstack 移植到 Claude Code、Codex、Pi 等运行时的技能栈skill stack。这些原则不需要你手动背诵——typescript-best-practices技能在读写.ts文件时会自动加载并优先应用类型系统纪律。相关路径资料路径原则原文8 个模式 6 问自检principle-type-system-discipline/SKILL.mdTypeScript 规则速查表typescript-best-practices/SKILL.md每条规则配套示例references/patterns.md原则总索引架构组poteto-mode/SKILL.md想体验完整工作流直接对 Agent 说一句话即可例如Use poteto-mode to fix the search filter resetting when I change pages它会自动选剧本、委派执行并给出失败与通过的证据。小结一句话记住原则 09类型系统不是 lint 工具是你的第一道运行时。把非法状态定义到不存在、给语义值打品牌、在边界解析外部数据、不对编译器撒谎、穷举交给编译器——绝大多数不可能的运行时崩溃会在编译期就消失。【免费下载链接】pstack-claudeClaude Code, Codex, Copilot, Pi, OpenCode, Gemini, and Prime Agent versions of Potetos pstack. Rigorous agent workflows with Cursor primitives translated for other harnesses.项目地址: https://gitcode.com/GitHub_Trending/ps/pstack-claude创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表