Skip to content

fix(api-compat): allow optional property additions to inline object literals#2036

Merged
Stephen Belanger (Qard) merged 1 commit into
mainfrom
fix/api-compat-optional-object-literal
May 21, 2026
Merged

fix(api-compat): allow optional property additions to inline object literals#2036
Stephen Belanger (Qard) merged 1 commit into
mainfrom
fix/api-compat-optional-object-literal

Conversation

@Qard
Copy link
Copy Markdown
Collaborator

Summary

  • areInterfaceSignaturesCompatible was flagging adding an optional property to an inline object literal type (e.g. mastra?: boolean on InstrumentationConfig.integrations) as a breaking change.
  • Root cause: it compared each property's type as a string, then only re-checked via isUnionTypeWidening when the strings differed. Inline object literals aren't unions, so any new field tipped it into "modified" territory.
  • Fix: delegate to the existing areObjectTypeDefinitionsCompatible helper when both sides are inline object literals, mirroring the pattern already in areTypeAliasSignaturesCompatible. Also apply the same delegation inside areObjectTypeDefinitionsCompatible itself so nested object literals are handled the same way.
  • Lifted the inline isObjectType helper to a module-scope isObjectLiteralType so the interface, object-literal, and intersection comparators share one definition.

After this lands, the js-api-compatibility (20) check on PRs that add optional integration keys (#1891, #1897, #1901, future SDK integrations) will pass instead of failing informationally.

Test plan

  • Added 4 regression tests in describe("areInterfaceSignaturesCompatible", ...):
    • optional property added to inline object literal (the InstrumentationConfig case) → passes
    • required property added → still rejected
    • property removed → still rejected
    • optional property added to deeply nested inline object literal → passes
  • pnpm exec vitest run tests/api-compatibility/api-compatibility.test.ts — all 14 interface-compat tests pass plus the rest of the file
  • pnpm run fix:formatting and pnpm run lint clean

#skip-changeset — this is a test-only change with no impact on the published package.

🤖 Generated with Claude Code

…iterals

areInterfaceSignaturesCompatible compared each property's type as a
string, then only re-checked via isUnionTypeWidening when the strings
differed. Adding an optional property to an inline object literal
(e.g. mastra?: boolean to InstrumentationConfig.integrations) flips the
string equality, isn't a union widening, and was incorrectly classified
as a breaking change — even though it's structurally backward-compatible
TypeScript.

Fix: delegate to the existing areObjectTypeDefinitionsCompatible helper
when both sides are inline object literals, mirroring the pattern already
in areTypeAliasSignaturesCompatible. Also apply the same delegation
inside areObjectTypeDefinitionsCompatible itself so nested object
literals get the same treatment.

Lifted the inline isObjectType helper to a module-scope
isObjectLiteralType so both call sites share it.

Adds 4 regression tests:
- optional property added to inline object literal (the InstrumentationConfig case)
- required property added → still rejected
- property removed → still rejected
- optional property added to deeply nested inline object literal

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@Qard Stephen Belanger (Qard) merged commit 0df56e2 into main May 21, 2026
82 of 84 checks passed
@Qard Stephen Belanger (Qard) deleted the fix/api-compat-optional-object-literal branch May 21, 2026 13:14
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants