Repository navigation
fix(types): accept undefined in optional fields under exactOptionalPropertyTypes - #84
Conversation
…opertyTypes Every optional field is now declared `field?: T | undefined`, so inputs that hold undefined (spread options, oRPC `base` and `spec` overrides) typecheck with `exactOptionalPropertyTypes`. Fields typed `unknown` already accept it. The root tsconfig turns the flag on, and namespace.test-d.ts fails, naming the field, when any optional field of an exported type rejects undefined. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Fip9tURz1rjTSGs89Ejg7H
ApprovabilityVerdict: Would Approve Macroscope's review found this PR approvable — This is a self-contained, backwards-compatible TypeScript declaration fix plus compile-time coverage; all changed implementation files are type-erased or configuration-only. It does not alter runtime behavior, schemas, deployment, or sensitive functionality. Needs human approval because:
Review your spending limits in Billing settings. You can add or adjust custom eligibility rules. Learn more. |
Codecov Report✅ All modified and coverable lines are covered by tests. 📢 Thoughts on this report? Let us know! |
There was a problem hiding this comment.
✅ No new issues found.
Reviewed changes
- Optional fields accept
undefined— every optional property inv3.0.ts,v3.1.tsandv3.2.tsnow readsfield?: T | undefined, so inputs carryingundefinedtypecheck underexactOptionalPropertyTypes; theunknown-typed fields (example/value/dataValue/requestBody) are left untouched since they already admit it. - Flag enabled — root
tsconfig.jsonturns onexactOptionalPropertyTypes, exercising the repo-local typecheck with it. - Regression guard —
namespace.test-d.tsgainsRejectsUndefined<T>, which fails and names the offending field when any optional field on any exported type rejectsundefined, plus a@ts-expect-errorcase that fails if the flag is ever turned off.
I independently verified the sweep is complete (only unknown fields omit | undefined; no required field gained it) and that the test is non-vacuous — reverting v3.2.ts PathItemObject.summary to summary?: string makes the tsc leg fail with namespace.test-d.ts(186,14): error TS2741: Property 'summary' is missing in type '{}'. CI is green on 12098de. No consumer impact: with the flag off (the default) field?: T | undefined is identical to field?: T.
deepseek-v4.1-flash (free via Pullfrog for OSS) | 𝕏

Requested by dinwwwh · project thread
Problem
Every optional field in
@openapi-spec/typeswas declaredfield?: T. WithexactOptionalPropertyTypes, an input that holdsundefineddoesn't typecheck, which is common when spreading options and is what the downgrader already accepts at runtime. oRPC exposes these types for itsJsonSchema,baseandspecoptions.Fix
v3.0.ts,v3.1.tsandv3.2.tsis nowfield?: T | undefined. Fields typedunknown(example,value,dataValue,requestBody) are left as they are since they already acceptundefined.tsconfig.jsonturns onexactOptionalPropertyTypes, so the type tests and the downgrader tests compile with it. The downgrader tests that passdescription: undefinedandsummary: undefinedfailed to compile under the flag before this change.namespace.test-d.tsreuses its lists of every exported type and fails, naming the field, when any optional field rejectsundefined(plusSchemaObject<string>for the genericconst/default/example). A@ts-expect-errorcase makes the check fail if the flag is ever turned off.Verified locally:
pnpm run checkandpnpm testpass; reverting one field (operationId) fails withProperty 'operationId' is missing in type '{}', and removing the flag fails with an unused@ts-expect-error.Generated by Claude Code