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

Error with tsc when attempting to import types from RTK Query using @reduxjs/toolkit 2.0.1 #3970

Closed
ryerrappa opened this issue Dec 10, 2023 · 18 comments
Labels
bug Something isn't working rtk-query typescript
Milestone

Comments

@ryerrappa
Copy link

Sample repo reproducing the issue can be found here: https://github.com/ryerrappa/rtk-query-type-import-issue

  • @reduxjs/tookit 2.0.1
  • Vite 5.0.0
  • Typescript 5.2.2
  • tsconfig moduleResolution "bundler"

Receive the following error when attempting to import the MutationTrigger type.

Cannot find module @reduxjs/toolkit/dist/query/react/buildHooks

Using vite with the following tsconfig.

{
  "compilerOptions": {
    "composite": true,
    "skipLibCheck": true,
    "module": "ESNext",
    "moduleResolution": "bundler",
    "allowSyntheticDefaultImports": true
  },
  "include": ["vite.config.ts"]
}
@markerikson
Copy link
Collaborator

Yeah, the problem is you're specifically referencing that path, and it doesn't exist :)

import {MutationTrigger} from "@reduxjs/toolkit/dist/query/react/buildHooks";

That type is actually internal - I don't think we export it.

Why are you trying to use it?

@ryerrappa
Copy link
Author

Ahh, thanks for letting me know. I was previously importing it on a pre 2.0 version of RTK.

My use case was to send the mutation trigger along with some other args to a util function that performs some common functionality to all mutations belonging to a specific API. Something like

export const handleSubmitFormMutation = async <
  ServiceMethod extends MutationTrigger<never>,
  RequestBody
>(
  serviceMethod: ServiceMethod,
  serviceMethodArg: Parameters<ServiceMethod>[0],
  successHandler: () => void,
  setFormError: UseFormSetError<RequestBody>
) => {
  try {
    await serviceMethod(serviceMethodArg).unwrap();
    // Some other stuff
  } catch (error) {
    // setting errors on the form
}

@lcharlois-neotys
Copy link

Hello,

I'm facing the same kind of issue with the UseQuery type.

import { UseQuery } from '@reduxjs/toolkit/dist/query/react/buildHooks';

The use case is globally the same, having a utility method doing generic things on hooks results.

It will be nice to see these types being exported if possible.

@markerikson markerikson modified the milestones: Post 2.0, 2.x bugfixes Dec 11, 2023
@lcharlois-neotys
Copy link

@markerikson Would you accept a PR for this issue?

@markerikson
Copy link
Collaborator

Probably, yeah, if it's just exporting some additional types. Most of our types have been internal, because we didn't anticipate end users trying to make use of them.

@EskiMojo14
Copy link
Collaborator

EskiMojo14 commented Dec 12, 2023

for what it's worth, with passing triggers I tend to just type them based on how I intend to use them. For example, with the above example:

export const handleSubmitFormMutation = async <
  MutationArg,
  RequestBody
>(
  serviceMethod: (arg: MutationArg) => { unwrap(): Promise<unknown> },
  serviceMethodArg: MutationArg,
  successHandler: () => void,
  setFormError: UseFormSetError<RequestBody>
) => {
  try {
    await serviceMethod(serviceMethodArg).unwrap();
    // Some other stuff
  } catch (error) {
    // setting errors on the form
  }
}

that way, you're putting forward a minimum contract you expect from the trigger, and Typescript can compare your trigger against the contract to make sure it's compatible.

@TNMCook
Copy link

TNMCook commented Dec 15, 2023

I'm in the same boat as @lcharlois-neotys. I have a function that expects a query hook as a parameter and acts as a utility to handle various status changes and extract some common data. It looks something like this:

const usefulUtility = <ResultType>((queryHook: UseQuery<QueryDefinition<unknown, BaseQueryFn, string, ResultType>>, queryArg?: unknown) => {
    ...
    const {data, isSuccess, isError} = queryHook(queryArg);
    ...
    // Do useful stuff that would otherwise be repeated in multiple places 
    ...
}

It would be nice to have a type to easily encapsulate what a useWhateverQuery hook looks like. I've worked around it with my own type of (arg?: QueryArg) => TypedUseQueryHookResult<ResultType, QueryArg, BaseQueryFn>, but it would be nice to have a user accessible type for what a useSomethingQuery() looks like.

@ryerrappa
Copy link
Author

@EskiMojo14 That seems to work well. Thanks for your suggestion!

@tylerlaprade
Copy link

tylerlaprade commented Feb 1, 2024

I have the same problem. I'm importing both UseMutation and MutationTrigger from @reduxjs/toolkit/dist/query/react/buildHooks, as well as EndpointBuilder and EndpointDefinitions from @reduxjs/toolkit/dist/query/endpointDefinitions, but that's causing me problems with TypeScript now attempting to typecheck Redux files in my node_modules/. I would greatly appreciate these types being exposed, since they're useful when writing generic functions to interact with or generically generate RTKQ functions.

@lcharlois-neotys
Copy link

@tylerlaprade I'm working on a PR to expose more types.

For EndpointBuilder and EndpointDefinitions you can already import them like this as they are exported.

import { EndpointBuilder } from '@reduxjs/toolkit/query';

lcharlois-neotys added a commit to lcharlois-neotys/redux-toolkit that referenced this issue Feb 2, 2024
@tylerlaprade
Copy link

image I was able to switch `EndpointDefinitions` but not `EndpointBuilder`. However, I'm still on version `1.9.7`, so that might explain why it isn't available. image

@kThayer2
Copy link

kThayer2 commented Feb 2, 2024

Could we add UseLazyQuery as an exported type?

@EskiMojo14
Copy link
Collaborator

@tylerlaprade correct, EndpointBuilder was first exported from 2.0.

@kThayer2 could you give an example of how you'd use it?

@kThayer2
Copy link

kThayer2 commented Feb 2, 2024

@EskiMojo14 Good question! We are mocking it for unit testing:

/**
 * @example
 * const [trigger, result] = mockLazyQuery(useLazyGetEquipmentListQuery, {
 *   result: {
 *     data: {
 *       the: 'data',
 *     }
 *   }
 * })
 * expect(result.data).toEqual({the: 'data'})
 */
export function mockLazyQuery<T extends MockUseLazyQuery>(
  useLazyQuery: UseLazyQuery<any>,
  options?: MockUseLazyQueryResult<T>,
) {
  throwIfNotMock(useLazyQuery)

  const trigger = options?.trigger ?? vi.fn()
  const result = {
    ...options?.result,
  }

  vi.mocked(useLazyQuery).mockImplementation(() => [trigger, result] as any)

  return {
    trigger,
    result,
  }
}

@markerikson markerikson added bug Something isn't working rtk-query typescript labels Feb 5, 2024 — with Volta.net
@EskiMojo14
Copy link
Collaborator

The type helpers from #4147 have been released in version 2.2.0.

For what it's worth @kThayer2 we generally recommend using the real hooks and real network requests, and intercepting using MSW, rather than mocking hooks.

@tylerlaprade
Copy link

Thanks @EskiMojo14! Would it be possible to add a type for UseMutation as well? That's my only remaining dist/ import.

@EskiMojo14
Copy link
Collaborator

@tylerlaprade TypedUseMutation is exported, it just takes different (friendlier) generics.

@shrouxm
Copy link
Contributor

shrouxm commented Mar 21, 2024

I created a PR exposing one more type: #4289, merging would allow me to upgrade to RTK 2!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working rtk-query typescript
Projects
None yet
Development

No branches or pull requests

8 participants