Skip to content
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

transformResponse in enhanceEndpoints returning Promise type when trying to transform the type of the response #3443

Closed
cini9 opened this issue May 15, 2023 · 25 comments · Fixed by #3500
Milestone

Comments

@cini9
Copy link

cini9 commented May 15, 2023

Following the update to V1.9.4, with the ability to override TS type of the original data in transformResponse of enhanceEndpoints, the response type I am receiving in my components are being additionally transformed to add a Promise<> type of my desired response type.

I am using codegen to generate types from my backend, but need to transform that response to extract lower-level data from the raw graphql query response.

type TransformedGetUser = GetUserQuery['getUser']
type TransformedGetUsers = GetUsersQuery['getUsers']

type Definitions = DefinitionsFromApi<typeof generatedUserApi>
type TagTypes = TagTypesFromApi<typeof generatedUserApi>

type UpdatedDefinitions = Omit<Definitions, 'getUsers' | 'getUser'> & {
  getUsers: OverrideResultType<Definitions['getUsers'], TransformedGetUsers>
  getUser: OverrideResultType<Definitions['getUser'], TransformedGetUser>
}

const userApi = generatedUserApi.enhanceEndpoints<TagTypes, UpdatedDefinitions>(
  {
    endpoints: {
      getUsers: {
        providesTags: ['User'],
        transformResponse: (response: GetUsersQuery): TransformedGetUsers =>
          response.getUsers,
      },
      getUser: {
        providesTags: ['User'],
        transformResponse: (response: GetUserQuery): TransformedGetUser =>
          response.getUser,
      },
    },
  }
)

This gives me the typing in the components in the screen shot below, with my correct type (id: string, firstName: string, etc) followed by the Promise<...> type.

image

When I try to use the data returned from these queries, I'm getting a 'property id does not exist on type Promise< .... >'

image

Is there any way to tell RTK to not add the Promise type when we are overriding the response type in transformResponse ?

Thanks in advance for your help !

@quentingirard
Copy link

@dmitrigrabov did you find any solution ?

Is there a way that I can help ?

@Mozzarella123
Copy link

Mozzarella123 commented May 31, 2023

The main problem is that transformResponse can return Promise in types. And when we use query data it becomes MaybePromise

image

): ResultType | Promise<ResultType>

@cini9

@cini9
Copy link
Author

cini9 commented Jun 1, 2023

@Mozzarella123 Thanks for the update ! Is this the correct behaviour ? If so, how can I override this to obtain only the ResultType in my components ?

@EskiMojo14
Copy link
Collaborator

EskiMojo14 commented Jun 2, 2023

Hi there, thanks for the report! Apologies for the slow response.

The issue appears to be that the utility type used to extract the result from the provided type didn't account for Promises, as the actual execution unwraps that promise.

I've opened #3500 that should fix this - if someone could try the build that's created from that PR, that'd be greatly appreciated.

In terms of overriding result types, we're investigating (over at #3485) the possibility of replacing enhanceEndpoints entirely, with two functions - addTagTypes and enhanceEndpoint. This would greatly simplify typings and thus use cases such as replacing return types.

const enhanced = api
  .addTagTypes('tag1', 'tag2')
  .enhanceEndpoint('query1', { providesTags: ['tag1'] })
  .enhanceEndpoint('mutation2', (definition) => {
    definition.invalidatesTags = ['tag2'];
  })

This is of course a big breaking change, so it would be part of RTK 2.0, clearly communicated, and a codemod would most likely be provided to ease the transition.

@quentingirard
Copy link

Hey, thanks for the update

I've tried on my side and it sounds good !

@cini9
Copy link
Author

cini9 commented Jun 2, 2023

Hey @EskiMojo14 thanks for the fix ! I've checked it out and it seems to fix the Promise issue on my side as well !

@EskiMojo14
Copy link
Collaborator

great 😄

both of the other co-maintainers are at conferences this week so I'm unsure when we can get the fix reviewed, merged and published - will try to get it prioritised when possible 🙂

@quentingirard
Copy link

Hey @EskiMojo14,

Do you have any idea when it can be checked and released ?

@EskiMojo14
Copy link
Collaborator

it's been merged into master, but i'm not sure when the next release will be

@annaet
Copy link

annaet commented Jun 27, 2023

@EskiMojo14 Any chance of getting a new release out including this fix? It would be really useful for my team 😄

@markerikson markerikson added this to the 1.9.x milestone Jun 27, 2023
@markerikson
Copy link
Collaborator

I'll look at trying to get out another release sometime today.

@quentingirard
Copy link

Hey !

Same as @annaet, would it be possible to get a new release this week ?

@annaet
Copy link

annaet commented Jul 10, 2023

Hi @markerikson. Any updates on getting a new release out?

@cini9
Copy link
Author

cini9 commented Jul 19, 2023

Hi @markerikson and @EskiMojo14, I hope you guys are doing well. Sorry to keep pushing this issue, but do you have any updates on when you plan to release this fix ? I am currently working with a specific commit bundle in my package.json, which I think may have expired and is no longer accessible as a yarn package. Any info would be greatly appreciated so that we can plan our releases accordingly.

Thanks !

@markerikson
Copy link
Collaborator

I'm on vacation for at least another week, and won't have time to think about doing any releases until after I'm back.

@cini9
Copy link
Author

cini9 commented Jul 20, 2023

Alright thanks for the update ! Enjoy your vacation 🍸 🍺 🏖️

@annaet
Copy link

annaet commented Aug 1, 2023

@cini9 If you are using yarn or pnpm you can use the patch command to apply this fix to your project. This is what I'm doing until we get a new release: https://yarnpkg.com/cli/patch

@EskiMojo14
Copy link
Collaborator

the npm equivalent would be using something like patch-package

@Davgus
Copy link

Davgus commented Nov 21, 2023

Would love to see this released @markerikson

Isn't it already released in v1.9.6?

@Valli-
Copy link

Valli- commented Nov 21, 2023

Would love to see this released @markerikson

Isn't it already released in v1.9.6?

Ye, my bad, was on 1.9.5, a simpel upgrade solved my issue :)

@Innders
Copy link

Innders commented Jun 15, 2024

Thanks @cini9 you really helped me solve this problem.

  1. Now it's 2024 and we are on 2.2.5. Has anything changed in your setup for this?

  2. How are you dealing with when you have to use updateQueryData. If you perform this on a query you have overwritten the types, the types of draft will still be the generated ones not your transformed ones.

  3. Have you managed override the arguments type for queries/mutations?

  4. How do you find performance, it seems to take a good 20 seconds for my types to update, my macbook air M1 is struggling (for first time ever).

@cini9
Copy link
Author

cini9 commented Jun 17, 2024

Thanks @cini9 you really helped me solve this problem.

  1. Now it's 2024 and we are on 2.2.5. Has anything changed in your setup for this?
  2. How are you dealing with when you have to use updateQueryData. If you perform this on a query you have overwritten the types, the types of draft will still be the generated ones not your transformed ones.
  3. Have you managed override the arguments type for queries/mutations?
  4. How do you find performance, it seems to take a good 20 seconds for my types to update, my macbook air M1 is struggling (for first time ever).

Hey @Innders, I'm glad this discussion was able to help you solve this issue 😄. It is indeed useful to be able to modify the response type to fit our applications. I've tried to answer your questions above as best I could, but feel free to ask if you have any other questions.

  1. Nothing has really changed in our setup for this. We are still using the OverrrideResultType utility that we're getting from the reduxjs lib. We try to code split as much as possible (where it makes sense of course) to simplify our files. My structure is as follows :
    Screenshot 2024-06-17 at 11 42 35
    Where "documents" is where we keep our graphql queries and mutations, "generated" is where codegen generates all of the types, APIs and so on, and "enhanced", where we essentially enhance the query and modify the type as needed :
    Screenshot 2024-06-17 at 11 44 29

  2. I'm not 100% sure I understand what you mean for this one. We haven't used updateQueryData yet so I won't be able to provide any feedback on keeping the modified types for this one. If anyone else has this experience, please feel free to share your experience ! I'd also be glad to know if you figure out how to do this.

  3. We haven't yet had to modify the argument types for queries/mutations either. So far we've always defined exactly what we need for a mutation in our backend (which we try to keep as single source of truth), and codegen does a pretty good job of creating the input type.

  4. I have a Macbook Pro (pre M1) and honestly haven't noticed too much issue with performance. Typescript always takes a couple seconds to update everywhere when I change a type, but otherwise it doesn't lag too much.

I'd also love to get the community feedback if anybody has found a better way to do all of this !

@Innders
Copy link

Innders commented Jun 17, 2024

We try to code split as much as possible

Cool! I like your file structure... I might have to copy take inspiration from it. 😉

I'm not 100% sure I understand what you mean for this one. We haven't used updateQueryData

Let's say you enhance a simple query and then transform it so it just returns the number of edges in the response.

The first bit works great.

image

Now let's say you want to update the cache of that same query using updateQueryData so you can optimistically update the cache or for whatever reason.

The draft for the cache uses the original query type not the transformed type (number).

image

Maybe this is a bug in OverrideResultType or something. If you haven't used it then I wouldn't expect any help but I'm just putting it out there for anyone else 😄

We haven't yet had to modify the argument types.

Makes sense as you would only ever need to have new arguments if you were using onCacheEntryAdded. It would be nice to have a place to pass "meta" or "other" data to queries that aren't explicitly tied to the query.

I'd also love to get the community feedback.

This might be a good place: #3692

@EskiMojo14
Copy link
Collaborator

enhanceEndpoints cannot change the type of your existing API instance - you need to use the version it returns instead, which has updated types.

@Innders
Copy link

Innders commented Jun 17, 2024

you need to use the version it returns instead

That's so obvious 🤦

Works like a charm now, thank you so much! 🎉

image
image

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 a pull request may close this issue.

9 participants