Skip to content

Add MethodResponse utility type #1831

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 4 commits into from
Aug 12, 2024

Conversation

SebastienGllmt
Copy link
Contributor

@SebastienGllmt SebastienGllmt commented Aug 8, 2024

Changes

Adds a new MethodResponse utility type to openapi-fetch to easily reference the return type of a fetch call in your code

How to Review

Understanding the rationale

There are many times in a codebase where you do something like this:

async function getData(...data): Promise<Data> {
   // 1) Process the data in some way
   // 2) Do some other async calls like DB queries or querying other services
  
   const { data, error } = await client.GET('/data', {});
   if (error != null) { /* handle case */ }
   return data;
}

The return type of this function is based solely on the data endpoint result, so it would be nice to make this relation explicitly clear

Before this PR

The easiest way to do this is the following code, is the following code

async function getData(): Promise<Awaited<ReturnType<typeof client.GET<'/data', {}>>>>

This has a problem though: if client isn't statically known as a global variable. In that case, you cannot get around this by just doing Client<paths>['GET']<'/data', {}> as this is not valid typescript

After this PR

This is the new code which is both shorter, and also works well even if typeof client is not possible and a type variable is used in its place

async function getData(): Promise<MethodResponse<typeof client, 'get', '/data'>>
// this also works
async function getData(): Promise<MethodResponse<MyClient, 'get', '/data'>>

Why not just use schemas?

Another option is to use components['schemas']['GetDataResponse'], which is also valid and just a matter of preference. I think being able to explicitly specify the connection between a method and the response is more flexible than this

For example, you could create a wrapper on the type I added to this library (which I don't think you can easily do before this PR), by doing something like

type GetType<Path extends PathsWithMethod<typeof client, 'get'>> = MethodResponse<
  typeof client,
  'get',
  Path
>;

// you can now use it like this
async function getData(): Promise<GetType<'/data'>>

Additionally, this components['schemas'] option isn't always guaranteed to work. For example, there are cases where the schema is partially inlined into the operations object:

export interface operations {
    GetData: {
        // ...
        responses: {
             200: {
                 content: {
                     "application/json": {
                        dataSummary: components["schemas"]["GetDataResponse"][];
                     }
                 }
             }
        }
    }
}

As you can see in this example, you cannot just use GetDataResponse directly because it's missing the fact it's actually contained inside a dataSummary object

Code

This is just a utility type, so there is no functionality change

Checklist

  • Unit tests updated
  • docs/ updated (if necessary)
  • pnpm run update:examples run (only applicable for openapi-typescript)

@SebastienGllmt SebastienGllmt requested a review from a team as a code owner August 8, 2024 20:27
@kerwanp kerwanp added the openapi-fetch Relevant to the openapi-fetch library label Aug 10, 2024
@drwpow
Copy link
Contributor

drwpow commented Aug 10, 2024

Thank you! You can add a patch Changeset if you like (see comment) so you’re credited with this.

Thanks for such a detailed writeup! You made a great argument for adding this utility, and this is a great addition.

Copy link

changeset-bot bot commented Aug 10, 2024

🦋 Changeset detected

Latest commit: d51ed16

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

This PR includes changesets to release 2 packages
Name Type
openapi-fetch Patch
openapi-react-query Patch

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

@drwpow drwpow merged commit 091e71a into openapi-ts:main Aug 12, 2024
7 checks passed
@github-actions github-actions bot mentioned this pull request Aug 12, 2024
@SebastienGllmt SebastienGllmt deleted the method-response-utility branch August 12, 2024 05:24
This was referenced Aug 13, 2024
@piousdeer
Copy link
Contributor

Why not use SuccessResponse from openapi-typescript-helpers?

async function getData(): Promise<SuccessResponse<paths['/data']['get']>>

@SebastienGllmt
Copy link
Contributor Author

@piousdeer MethodResponse uses SuccessResponse under-the-hood. It basically wraps that utility type to allow you to pass an arbitrary client as the source of the information (instead of having to pass in a specific paths type)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
openapi-fetch Relevant to the openapi-fetch library
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants