用途
该技能用于在 Pstack 任务中编写 TypeScript 类型、校验边界、可辨识联合或公共 API 时提供规范。使用时应先应用 /principle-type-system-discipline,边界相关问题另见 /principle-boundary-discipline。
主要规则
- 可辨识联合:用 kind 字面量判别字段建模各变体,使不可能状态无法被表示,避免用一堆可选字段拼凑。
- 品牌类型:用 & { readonly __brand: "X" } 给原始类型打品牌,防止混用;在边界处只校验一次。
- 构造式建模:让非法值无法被构造,例如用 [T, ...T[]] 表示非空、[T, T][] 表示偶数长度;数值范围约束仍需边界校验。
- 最简完备类型:当对 T[] 的每个操作都保持完备时保留 T[];只有在松散类型被迫使用 !、类型断言或“不应发生”的抛出时,才强化为 NonEmpty<T>。
- unknown 优于 any:外部数据视为 unknown。
- schema 先于类型守卫:手写逐属性类型守卫之前,先用仓库现有运行时 schema 库,并从 schema 推断类型,如 z.infer。
- 避免未校验断言:不要用绕过校验的断言;as const 保留字面量类型,经校验的构造函数可以断言品牌类型。
- 收窄优先级:判别式 switch > in 运算符 > typeof/instanceof > 用户定义类型守卫 > as。
- 类型守卫:必须真正验证其声明;说谎的守卫比 as 更糟,因为错误藏在声称安全的名字后面;命名用 isX 或 hasX。
- 穷尽性:在 default 分支内联 const _exhaustive: never = x; 使新增变体时编译器报错。
- satisfies 优于 as:检查是否符合目标类型而不把值标注为目标类型;上下文类型仍影响字面量推断。
- 边界校验:数据跨界进入时解析为具名领域类型,Record<string, unknown> 等宽松类型止于该解析处,内部信任类型。
- 由 schema 派生类型:声明新 interface 前先用 Pick/Omit/Parameters/ReturnType/Awaited/typeof。
- 对象参数:传对象而非位置参数,使参数顺序自解释;热路径(逐帧渲染、分词器、解析器)可跳过。
- 真实测试:能真实运行的就不要 mock,优先使用框架真实测试原语并做泄漏/可释放性检查,在运行构建中验证 UI;只 mock 本地无法运行的部分。
- 结构化遥测:优先用带足够上下文的日志诊断,能从 id 回溯;发布代码中不用 console.log。
使用方式
作为代理技能按上述规则指导 TypeScript 代码编写;示例见 references/patterns.md。具体的安装命令、调用接口和平台集成方式暂未提供。
适用场景与限制
适用于 TypeScript 类型设计、外部数据校验边界、公共 API 定义及测试与日志规范等场景。该技能为规则性指导,本身不提供运行时库;具体项目的 schema 库、测试框架等需沿用仓库既有选择,相关资料暂未提供。