Skip to content

Conversation

@abumalick
Copy link
Contributor

Summary

  • Add opt-in --read-write-markers flag that generates $Read<T> and $Write<T> marker types for readOnly/writeOnly OpenAPI properties
  • Wrap readOnly properties with $Read<T>, writeOnly with $Write<T>
  • Generate inline helper types (Readable, Writable) in output
  • Update openapi-fetch to use Writable<T> for request bodies and Readable<T> for responses

This enables proper type-checking:

  • readOnly properties are excluded from request bodies
  • writeOnly properties are excluded from response types

Closes #604

Test plan

  • Added TDD tests in packages/openapi-fetch/test/read-write-visibility/
  • Tests verify compile-time type errors for invalid usage
  • Tests verify runtime behavior
  • All existing tests pass

@changeset-bot
Copy link

changeset-bot bot commented Dec 16, 2025

🦋 Changeset detected

Latest commit: 46a6e86

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 4 packages
Name Type
openapi-typescript Minor
openapi-typescript-helpers Minor
openapi-fetch Minor
openapi-react-query Major

Not sure what this means? Click here to learn what changesets are.

Click here if you're a maintainer who wants to add another changeset to this PR

@netlify
Copy link

netlify bot commented Dec 16, 2025

👷 Deploy request for openapi-ts pending review.

Visit the deploys page to approve it

Name Link
🔨 Latest commit 46a6e86

@abumalick abumalick force-pushed the feat/read-write-markers branch 4 times, most recently from b3daedc to b1d920a Compare December 16, 2025 09:25
@abumalick abumalick marked this pull request as ready for review December 16, 2025 09:25
@abumalick abumalick requested a review from a team as a code owner December 16, 2025 09:25
@abumalick
Copy link
Contributor Author

this one is a new implementation of #1863 @drwpow FYI

Copy link

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

This PR adds opt-in support for OpenAPI's readOnly and writeOnly property modifiers via a new --read-write-markers CLI flag. When enabled, the type generator wraps these properties with marker types ($Read<T> and $Write<T>), enabling compile-time enforcement of visibility rules in openapi-fetch.

Key Changes:

  • Added --read-write-markers flag to wrap readOnly properties with $Read<T> and writeOnly properties with $Write<T>
  • Generated inline helper types (Readable<T>, Writable<T>) strip markers appropriately for request/response contexts
  • Updated openapi-fetch to use Writable<T> for request bodies and Readable<T> for responses

Reviewed changes

Copilot reviewed 11 out of 14 changed files in this pull request and generated 2 comments.

Show a summary per file
File Description
packages/openapi-typescript/src/types.ts Added readWriteMarkers option to OpenAPITSOptions and GlobalContext interfaces
packages/openapi-typescript/src/index.ts Wired up readWriteMarkers option from user input to global context
packages/openapi-typescript/bin/cli.js Added --read-write-markers CLI flag support
packages/openapi-typescript/src/transform/schema-object.ts Implemented wrapWithReadWriteMarker function and integrated marker wrapping for properties and $defs
packages/openapi-typescript/src/transform/index.ts Added inline generation of helper types ($Read, $Write, Readable, Writable) when flag is enabled
packages/openapi-typescript-helpers/src/index.ts Added exportable helper types for marker definitions and transformation utilities
packages/openapi-fetch/src/index.d.ts Applied Writable to request bodies and Readable to response data/errors
packages/openapi-typescript/test/transform/schema-object/object.test.ts Added comprehensive test cases for readWriteMarkers option behavior
packages/openapi-typescript/test/test-helpers.ts Added readWriteMarkers: false to default test context
packages/openapi-fetch/test/read-write-visibility/schemas/read-write.yaml Test schema with readOnly and writeOnly properties
packages/openapi-fetch/test/read-write-visibility/schemas/read-write.d.ts Generated types from test schema with markers enabled
packages/openapi-fetch/test/read-write-visibility/read-write.test.ts Runtime and compile-time tests verifying marker behavior
docs/cli.md Documentation for the new --read-write-markers flag with usage examples
.changeset/happy-pans-run.md Changeset describing the new feature

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

@abumalick abumalick force-pushed the feat/read-write-markers branch from b1d920a to 3dd3cf1 Compare December 16, 2025 10:03
@abumalick abumalick marked this pull request as draft December 16, 2025 11:06
@abumalick
Copy link
Contributor Author

mmh, sorry it is not fully ready yet, after more testing I get some bugs

@abumalick abumalick marked this pull request as ready for review December 24, 2025 06:51
@abumalick
Copy link
Contributor Author

Here it is ready incha Allah.
I tested it by migrating my enterprise's app to use this patched version. It is working well and it is really good to have this painful problem fixed.
I could remove all @ts-expect-errors on network requests payloads.

Please tell me if you need any changes or if you have any concern @htunnicliff @drwpow

@abumalick
Copy link
Contributor Author

@htunnicliff @drwpow any feedback please?

@htunnicliff htunnicliff removed their request for review December 30, 2025 17:23
@abumalick
Copy link
Contributor Author

Ping for feedback @drwpow @kerwanp @gzm0 @htunnicliff

This implements the readOnly/writeOnly markers discussed in #1863 following @drwpow's suggested approach.

Production validation: Running in 2 company projects with openapi-fetch + openapi-react-query. Eliminated nearly all @ts-expect-error annotations for request/response type mismatches.

Key decisions needing review:

  • Opt-in via --read-write-markers flag
  • $Read<T>/$Write<T> marker approach
  • Helper types in openapi-typescript-helpers

Happy to adjust based on feedback. Is this direction acceptable or should I take a different approach?

@abumalick
Copy link
Contributor Author

@duncanbeevers or any other maintainer. Can I get a review on this?

Copy link
Contributor

@drwpow drwpow left a comment

Choose a reason for hiding this comment

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

Wow, thanks for all the thought and effort put into this PR! This has been a long-requested feature, and this adds in the ability in what looks to be a far more backwards-compatible way than some alternate solutions. I was worried this would be a breaking change, and so this (and the draft PR) fell behind in getting it merged in. But your approach looks sound, and looks like it wouldn’t disrupt users.

For openapi-fetch we’ve been reserving minor releases for breaking changes, and even though this is is backwards-compatible, I think a minor change makes sense here given it requires a more recent version of openapi-typescript. Folks will be happy to get this merged and released, thank you! 🙂

@drwpow
Copy link
Contributor

drwpow commented Feb 8, 2026

It looks like the PR has some minor conflicts, if these get resolved I’d be happy to get this merged & released

Add opt-in `--read-write-markers` flag that generates `$Read<T>` and `$Write<T>`
marker types for readOnly/writeOnly OpenAPI properties.

- Wrap readOnly properties with `$Read<T>`
- Wrap writeOnly properties with `$Write<T>`
- Generate inline helper types (`Readable`, `Writable`) in output
- Update openapi-fetch to use `Writable<T>` for request bodies and `Readable<T>` for responses
- Add `$Read`, `$Write`, `Readable`, `Writable` types to openapi-typescript-helpers

This enables proper type-checking:
- readOnly properties are excluded from request bodies
- writeOnly properties are excluded from response types

Closes openapi-ts#604
When Readable<$Read<U>> was resolved, it returned U directly instead of
Readable<U>, causing nested $Read markers inside U to not be unwrapped.
Same issue for Writable<$Write<U>>.
@abumalick abumalick force-pushed the feat/read-write-markers branch from 61d7b87 to fd239b8 Compare February 9, 2026 04:55
@abumalick abumalick force-pushed the feat/read-write-markers branch from d8dd87b to 46a6e86 Compare February 9, 2026 05:03
@abumalick
Copy link
Contributor Author

Thanks @drwpow.

I really love this library and was really bothered by the typing issues with our APIs.
Since I started using the changes from this PR (as a patch) on our projects, we were able to confidently remove all TypeScript silencing and casting related to API types, and it greatly improved our confidence in the backend types. I am really happy with the result.

I was worried that you would not accept this change because of the complexity. I believe it makes a lot of sense to put this behind a flag so as not to bother users who don't need it or don't want to spend time refactoring their code for these changes.

Thank you for taking the time to work on this wonderful library.

@drwpow drwpow merged commit a690e52 into openapi-ts:main Feb 11, 2026
7 checks passed
@openapi-ts-bot openapi-ts-bot mentioned this pull request Feb 11, 2026
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.

Support "readOnly" and "writeOnly" OpenAPI properties

2 participants