$npx -y skills add remotion-dev/remotion --skill nullable-new-paramsFix newly added optional parameters, optional React props, and optional type/interface members in Remotion monorepo diffs by converting internal APIs to required nullable values and updating call sites. Use when a PR, review, or user asks to forbid new foo?: T / param?: T add
| 1 | # Nullable new params |
| 2 | |
| 3 | Use this skill when a change added a new parameter or type member as optional. In internal Remotion code, new inputs must be required and nullable so every caller makes an explicit choice. |
| 4 | |
| 5 | ## Rule |
| 6 | |
| 7 | - Internal contracts: write `name: T | null`, not `name?: T`. |
| 8 | - Call sites must pass `null` explicitly when no value exists. |
| 9 | - Implementation checks should prefer `value === null` / `value !== null` when null is the absence sentinel. |
| 10 | - Do not use `undefined` as the absence sentinel for new internal APIs unless the surrounding local contract already standardizes on `undefined`. |
| 11 | - The anti-pattern includes redundant shapes such as `frozenFrame?: number | null`; make it `frozenFrame: number | null`. |
| 12 | |
| 13 | Public APIs are the exception. If the changed signature, props type, or options object is exported from a package public entrypoint or documented in `packages/docs/docs`, making the new field/argument required is a breaking change. Keep it optional or add a backwards-compatible overload/options path, then document/default it as appropriate. |
| 14 | |
| 15 | ## Workflow |
| 16 | |
| 17 | 1. Inspect the diff for newly added optional members or parameters: |
| 18 | |
| 19 | ```sh |
| 20 | bun .agents/skills/nullable-new-params/scripts/find-new-optional-params.ts |
| 21 | ``` |
| 22 | |
| 23 | Useful variants: |
| 24 | |
| 25 | ```sh |
| 26 | bun .agents/skills/nullable-new-params/scripts/find-new-optional-params.ts origin/main...HEAD |
| 27 | bun .agents/skills/nullable-new-params/scripts/find-new-optional-params.ts --cached |
| 28 | ``` |
| 29 | |
| 30 | 2. For each candidate, classify whether it is public: |
| 31 | - Public: exported from a package entrypoint, included in package `exports`, or documented in `packages/docs/docs`. |
| 32 | - Internal: local helpers, internal component props, cross-file monorepo helpers, test utilities, internal context data, and types not exposed through package entrypoints. |
| 33 | - If unsure, grep package entrypoints and docs before changing API shape. |
| 34 | |
| 35 | 3. For internal candidates, refactor the type from optional to required nullable: |
| 36 | |
| 37 | ```ts |
| 38 | type Before = { |
| 39 | readonly frame?: number; |
| 40 | }; |
| 41 | |
| 42 | type After = { |
| 43 | readonly frame: number | null; |
| 44 | }; |
| 45 | ``` |
| 46 | |
| 47 | For function parameters: |
| 48 | |
| 49 | ```ts |
| 50 | const before = (frame?: number) => {}; |
| 51 | const after = (frame: number | null) => {}; |
| 52 | ``` |
| 53 | |
| 54 | 4. Update every caller/object literal to pass the value explicitly: |
| 55 | - Use `field: null` when absent. |
| 56 | - Preserve existing values with `field: maybeValue ?? null` only when `undefined` can still enter from surrounding code. |
| 57 | - Avoid hiding the required choice behind defaults in destructuring. |
| 58 | |
| 59 | 5. Update implementation logic: |
| 60 | - Replace truthy checks when `0`, `''`, or `false` are valid values. |
| 61 | - Prefer `value !== null` over `value` for nullable numbers/strings/booleans. |
| 62 | - Keep tests and fixtures explicit; do not make large fixtures `Partial<T>` only to dodge the new field. |
| 63 | |
| 64 | 6. For public candidates, preserve backwards compatibility: |
| 65 | - Keep the new field optional in the public type. |
| 66 | - Resolve a concrete internal value at the boundary, usually with `const internal = publicValue ?? null`. |
| 67 | - Keep internal downstream types required nullable. |
| 68 | |
| 69 | 7. Verify: |
| 70 | - Run the scanner again until only intentional public API exceptions remain. |
| 71 | - Run focused tests or package builds for touched packages, for example `bunx turbo run make --filter='<package-name>'`. |
| 72 | - If docs changed, follow the `writing-docs` skill. |
| 73 | |
| 74 | ## Review checklist |
| 75 | |
| 76 | - No new internal `?:` member or `param?:` parameter remains. |
| 77 | - Every internal caller passes either a real value or `null`. |
| 78 | - Public APIs remain backwards-compatible. |
| 79 | - Nullable checks do not treat valid falsy values as absent. |
| 80 | - Tests cover at least one explicit `null` path when behavior depends on absence. |