Skip to content

fix(types): accept undefined in optional fields under exactOptionalPropertyTypes - #84

Merged
dinwwwh merged 1 commit into
mainfrom
claude/project-thread-julewu
Oct 24, 2026
Merged

dinwwwh merged 1 commit into
mainfrom
claude/project-thread-julewu

Conversation

@dinwwwh

@dinwwwh dinwwwh commented Oct 24, 2026

Copy link
Copy Markdown
Member

Requested by dinwwwh · project thread

Problem

Every optional field in @openapi-spec/types was declared field?: T. With exactOptionalPropertyTypes, an input that holds undefined doesn't typecheck, which is common when spreading options and is what the downgrader already accepts at runtime. oRPC exposes these types for its JsonSchema, base and spec options.

declare const summary: string | undefined
// error under --exactOptionalPropertyTypes before this change
const op: OpenAPIV3_2.OperationObject = { summary, responses: {} }

Fix

  • Every optional field in v3.0.ts, v3.1.ts and v3.2.ts is now field?: T | undefined. Fields typed unknown (example, value, dataValue, requestBody) are left as they are since they already accept undefined.
  • The root tsconfig.json turns on exactOptionalPropertyTypes, so the type tests and the downgrader tests compile with it. The downgrader tests that pass description: undefined and summary: undefined failed to compile under the flag before this change.
  • namespace.test-d.ts reuses its lists of every exported type and fails, naming the field, when any optional field rejects undefined (plus SchemaObject<string> for the generic const/default/example). A @ts-expect-error case makes the check fail if the flag is ever turned off.

Verified locally: pnpm run check and pnpm test pass; reverting one field (operationId) fails with Property 'operationId' is missing in type '{}', and removing the flag fails with an unused @ts-expect-error.


Generated by Claude Code

…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
@dinwwwh dinwwwh self-assigned this Oct 24, 2026
@macroscopeapp

macroscopeapp Bot commented Oct 24, 2026

Copy link
Copy Markdown

Approvability

Verdict: 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:

  • Insufficient credits. Approvability relies on correctness review in order to determine eligibility

Review your spending limits in Billing settings. You can add or adjust custom eligibility rules. Learn more.

@codspeed

codspeed Bot commented Oct 24, 2026

Copy link
Copy Markdown

Merging this PR will not alter performance

✅ 21 untouched benchmarks


Comparing claude/project-thread-julewu (12098de) with main (1017e01)

Open in CodSpeed

@codecov

codecov Bot commented Oct 24, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.

📢 Thoughts on this report? Let us know!

@pullfrog pullfrog Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

✅ No new issues found.

Reviewed changes

  • Optional fields accept undefined — every optional property in v3.0.ts, v3.1.ts and v3.2.ts now reads field?: T | undefined, so inputs carrying undefined typecheck under exactOptionalPropertyTypes; the unknown-typed fields (example/value/dataValue/requestBody) are left untouched since they already admit it.
  • Flag enabled — root tsconfig.json turns on exactOptionalPropertyTypes, exercising the repo-local typecheck with it.
  • Regression guard — namespace.test-d.ts gains RejectsUndefined<T>, which fails and names the offending field when any optional field on any exported type rejects undefined, plus a @ts-expect-error case 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.

Pullfrog  | View workflow run | Using deepseek-v4.1-flash (free via Pullfrog for OSS) | 𝕏

@dinwwwh
dinwwwh merged commit c78a39b into main Oct 24, 2026
11 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants