用途
nullable-new-params 用于在 Remotion monorepo 的代码变更(diff)中,处理新添加的可选参数、可选 React props 以及可选类型/接口成员。当一次改动把新的参数或类型成员定义为可选时,使用该技能进行规范化。
核心规则
在 Remotion 内部代码中,新增输入必须是必填且可为 null 的,以便每个调用方都做出明确选择。
- 内部契约:写
name: T | null,而不是name?: T。 - 调用点在没有值时必须显式传入
null。 - 当 null 是缺失哨兵值时,实现检查应优先使用
value === null/value !== null。 - 除非周围局部契约已经统一使用 undefined,否则不要将 undefined 作为新内部 API 的缺失哨兵值。
- 反模式包括冗余形态,例如
frozenFrame?: number | null;应改为frozenFrame: number | null。
公共 API 是例外。如果变更后的签名、props 类型或 options 对象从包的公共入口导出,或在 packages/docs/docs 中有文档记录,那么把新字段/参数设为必填属于破坏性变更。此时应保持可选,或添加向后兼容的重载/options 路径,并按需记录文档或设置默认值。
工作流程
- 检查 diff 中新增的可选成员或参数:
bun .agents/skills/nullable-new-params/scripts/find-new-optional-params.ts
可用变体:
bun .agents/skills/nullable-new-params/scripts/find-new-optional-params.ts origin/main...HEAD
bun .agents/skills/nullable-new-params/scripts/find-new-optional-params.ts --cached
- 对每个候选项,判断其是否为公共 API:
- 公共:从包入口导出、包含在 package exports 中,或在
packages/docs/docs中有文档记录。 - 内部:本地辅助函数、内部组件 props、跨文件 monorepo 辅助函数、测试工具、内部上下文数据,以及未通过包入口暴露的类型。
如果不确定,在改变 API 形态前先 grep 包入口和文档。
- 对内部候选项,将类型从可选重构为必填可空:
type Before = {
readonly frame?: number;
};
type After = {
readonly frame: number | null;
};
对于函数参数:
const before = (frame?: number) => {};
const after = (frame: number | null) => {};
- 更新每个调用方/对象字面量,显式传入值:
- 缺失时使用
field: null。 - 仅当 undefined 仍可能从周围代码进入时,才用
field: maybeValue ?? null保留现有值。 - 避免在解构中用默认值隐藏这个必填选择。
- 更新实现逻辑:
- 当 0、'' 或 false 是有效值时,替换真值检查。
- 对于可空数字/字符串/布尔值,优先使用
value !== null而不是value。 - 更新现有测试或 fixture 时保持显式;不要为了让新字段通过而把大型 fixture 改成
Partial<T>。
- 对公共候选项,保持向后兼容:
- 在公共类型中保持新字段可选。
- 在边界处解析出具体内部值,通常用
const internal = publicValue ?? null。 - 保持下游内部类型为必填可空。
- 验证:
- 再次运行扫描器,直到只剩有意的公共 API 例外。
- 对受影响的包运行聚焦测试或包构建,例如
bunx turbo run make --filter='<package-name>'。 - 如果文档有变更,遵循 writing-docs 技能。
审查清单
- 不再残留新的内部
?:成员或param?:参数。 - 每个内部调用方都传入真实值或 null。
- 公共 API 保持向后兼容。
- 可空检查不会把有效的假值当作缺失。
- 当行为依赖缺失状态时,通过现有检查或手动验证确认显式 null 路径。
适用场景
适用于 Remotion monorepo 内部代码变更,尤其是新增可选参数、可选 React props 或可选类型/接口成员时。公共 API 的变更需要特殊处理以保持向后兼容。
限制
该技能针对 Remotion 仓库的内部约定,不适用于其他项目。公共 API 与内部 API 的区分需要人工判断,必要时需查阅包入口和文档。